[Ameba] Shell commands update (#23005)

* [Shell] Read cluster attributes from matter shell
- Received data but DataResponse is still not printed out
- Support more OnOff commands for matter shell

* [Shell] enable inputting arguments for certain commands

* [Shell] Add levelcontrol commands to shell
- Separate different cluster commands into header files

* [Shell] Add colorcontrol commands to shell

* [Shell] Add thermostat commands to shell

* [Shell] Add handlers for group commands

* [README] Update readme for all-clusters-app

* [Shell] Add identify commands to shell

* [Shell] Increase the number of tokens to fit more arguments
- Add in missing colorcontrol commands
- Fix readme link

* [Shell] Enable reading of attribute list

* [Shell] Fix transition data type and argument errors
- Added logs for levelcontrol commands

* [Shell] Fix compile errors for when CONFIG_ENABLE_CHIP_SHELL is disabled
- Added CONFIG_ENABLE_CHIP_SHELL macro to block off code that requires shell

* [Resyle] fix styling

* Restyled by prettier-markdown

* [Shell] Change ColorTemperature to ColorTemperatureMireds

* [Readme] Update all-clusters-app readme

* [Shell] Change currentx and currenty to current-x and current-y respectively
- To avoid spell check failing as it identifies currenty as mispelling of currently

* [Readme] Restyle

* [Shell] Fix typecasting error

* [Shell] restyle

Co-authored-by: Restyled.io <commits@restyled.io>
diff --git a/config/ameba/chip.cmake b/config/ameba/chip.cmake
index a6e6968..515bff6 100644
--- a/config/ameba/chip.cmake
+++ b/config/ameba/chip.cmake
@@ -30,6 +30,7 @@
     -DCHIP_DEVICE_LAYER_TARGET=Ameba
     -DMBEDTLS_CONFIG_FILE=<mbedtls_config.h>
     -D_POSIX_REALTIME_SIGNALS
+    -DCHIP_SHELL_MAX_TOKENS=11
 )
 
 list(
diff --git a/examples/all-clusters-app/ameba/README.md b/examples/all-clusters-app/ameba/README.md
index ddbdf66..a710a2e 100644
--- a/examples/all-clusters-app/ameba/README.md
+++ b/examples/all-clusters-app/ameba/README.md
@@ -14,7 +14,7 @@
     -   [Cluster control](#cluster-control)
     -   [Running RPC Console](#running-rpc-console)
     -   [Running Matter Shell](#running-matter-shell)
-    -   [Binding and Controlling a Lighting Device](#binding-and-controlling-a-lighting-device)
+    -   [Binding and Controlling a Device](#binding-and-controlling-a-device)
 
 ---
 
@@ -137,28 +137,55 @@
 
 -   Open the USB-TTL serial port and type `help` to view the available commands
 
-## Binding and Controlling a Lighting Device
+-   To know what are the available subcommands are there, enter `switch` command
+    in the shell
 
--   This example shows how to bind a Switch Device to a Lighting Device and
+## Binding and Controlling a Device
+
+-   This example shows how to bind a Switch Device to a Controllee Device and
     control it through the Matter Shell. One binding client (Switch Device) and
-    one binding server (Lighting Device) is required.
+    one binding server (Controllee) is required.
 
--   Commission the switch (nodeID 1) and lighting device (nodeID 2) using
+-   Commission the switch (nodeID 1) and controllee device (nodeID 2) using
     chip-tool.
 
               $ ./chip-tool pairing ble-wifi 1 <SSID> <PASSWORD> 20202021 3840
               $ ./chip-tool pairing ble-wifi 2 <SSID> <PASSWORD> 20202021 3840
 
-*   After successful commissioning, configure the ACL in the lighting device to
-    allow access from switch device and chip-tool.
+-   After successful commissioning, configure the ACL in the controllee device
+    to allow access from switch device and chip-tool.
 
               $ ./chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null },{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [1], "targets": null }]' 2 0
 
--   Bind the lighting device to the switch device.
+-   Bind the endpoint 1 OnOff cluster of the controllee device to the switch
+    device.
 
               $ ./chip-tool binding write binding '[{"fabricIndex": 1, "node":2, "endpoint":1, "cluster":6}]' 1 1
 
--   Control the lighting device through the switch device's Matter Shell
+-   Send OnOff command to the device through the switch device's Matter Shell
 
-              > switch onoff on
-              > switch onoff off
+    `switch onoff on`
+
+    `switch onoff off`
+
+*   You may also bind more than one cluster to the switch device. Below command
+    binds the Identify, OnOff, LevelControl, ColorControl and Thermostat
+    clusters to the switch device.
+
+              $ ./chip-tool binding write binding '[{"fabricIndex": 1, "node":2, "endpoint":1, "cluster":3}, {"fabricIndex": 1, "node":2, "endpoint":1, "cluster":6}, {"fabricIndex": 1, "node":2, "endpoint":1, "cluster":8}, {"fabricIndex": 1, "node":2, "endpoint":1, "cluster":768}, {"fabricIndex": 1, "node":2, "endpoint":1, "cluster":513}]' 1 1
+
+-   After binding the clusters, you may send these cluster commands to the
+    controllee device through the switch device's Matter Shell. Follow the
+    format shown in the description of the commands.
+
+    `switch onoff on`
+
+    `switch levelcontrol movetolevel 100 0 0 0`
+
+    `switch colorcontrol movetohue 100 0 0 0 0`
+
+    `switch thermostat SPRL 0 0`
+
+*   You may also request to read cluster attributes from Matter Shell
+
+    `switch <cluster> read <attribute>`
diff --git a/examples/all-clusters-app/ameba/chip_main.cmake b/examples/all-clusters-app/ameba/chip_main.cmake
index 35d0b28..50d0d2d 100755
--- a/examples/all-clusters-app/ameba/chip_main.cmake
+++ b/examples/all-clusters-app/ameba/chip_main.cmake
@@ -255,6 +255,7 @@
     -DUSE_ZAP_CONFIG
     -DCHIP_HAVE_CONFIG_H
     -DMBEDTLS_CONFIG_FILE=<mbedtls_config.h>
+    -DCHIP_SHELL_MAX_TOKENS=11
 )
 
 if (matter_enable_persistentstorage_audit)
diff --git a/examples/all-clusters-app/ameba/main/BindingHandler.cpp b/examples/all-clusters-app/ameba/main/BindingHandler.cpp
index 29acdaa..64ccb61 100644
--- a/examples/all-clusters-app/ameba/main/BindingHandler.cpp
+++ b/examples/all-clusters-app/ameba/main/BindingHandler.cpp
@@ -17,10 +17,15 @@
  */
 
 #include "BindingHandler.h"
-#include "app/CommandSender.h"
+#include "ColorControlCommands.h"
+#include "IdentifyCommand.h"
+#include "LevelControlCommands.h"
+#include "OnOffCommands.h"
+#include "ThermostatCommands.h"
 #include "app/clusters/bindings/BindingManager.h"
 #include "app/server/Server.h"
 #include "controller/InvokeInteraction.h"
+#include "controller/ReadInteraction.h"
 #include "platform/CHIPDeviceLayer.h"
 #include <app/clusters/bindings/bindings.h>
 #include <lib/support/CodeUtils.h>
@@ -40,95 +45,84 @@
 using Shell::streamer_printf;
 
 Engine sShellSwitchSubCommands;
-Engine sShellSwitchOnOffSubCommands;
-
 Engine sShellSwitchGroupsSubCommands;
-Engine sShellSwitchGroupsOnOffSubCommands;
-
 Engine sShellSwitchBindingSubCommands;
 #endif // defined(ENABLE_CHIP_SHELL)
 
 namespace {
-
-void ProcessOnOffUnicastBindingCommand(CommandId commandId, const EmberBindingTableEntry & binding,
-                                       OperationalDeviceProxy * peer_device)
-{
-    auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) {
-        ChipLogProgress(NotSpecified, "OnOff command succeeds");
-    };
-
-    auto onFailure = [](CHIP_ERROR error) {
-        ChipLogError(NotSpecified, "OnOff command failed: %" CHIP_ERROR_FORMAT, error.Format());
-    };
-
-    VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady());
-    switch (commandId)
-    {
-    case Clusters::OnOff::Commands::Toggle::Id:
-        Clusters::OnOff::Commands::Toggle::Type toggleCommand;
-        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
-                                         toggleCommand, onSuccess, onFailure);
-        break;
-
-    case Clusters::OnOff::Commands::On::Id:
-        Clusters::OnOff::Commands::On::Type onCommand;
-        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
-                                         onCommand, onSuccess, onFailure);
-        break;
-
-    case Clusters::OnOff::Commands::Off::Id:
-        Clusters::OnOff::Commands::Off::Type offCommand;
-        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
-                                         offCommand, onSuccess, onFailure);
-        break;
-    }
-}
-
-void ProcessOnOffGroupBindingCommand(CommandId commandId, const EmberBindingTableEntry & binding)
-{
-    Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager();
-
-    switch (commandId)
-    {
-    case Clusters::OnOff::Commands::Toggle::Id:
-        Clusters::OnOff::Commands::Toggle::Type toggleCommand;
-        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, toggleCommand);
-        break;
-
-    case Clusters::OnOff::Commands::On::Id:
-        Clusters::OnOff::Commands::On::Type onCommand;
-        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, onCommand);
-
-        break;
-
-    case Clusters::OnOff::Commands::Off::Id:
-        Clusters::OnOff::Commands::Off::Type offCommand;
-        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, offCommand);
-        break;
-    }
-}
-
 void LightSwitchChangedHandler(const EmberBindingTableEntry & binding, OperationalDeviceProxy * peer_device, void * context)
 {
     VerifyOrReturn(context != nullptr, ChipLogError(NotSpecified, "OnDeviceConnectedFn: context is null"));
     BindingCommandData * data = static_cast<BindingCommandData *>(context);
 
-    if (binding.type == EMBER_MULTICAST_BINDING && data->isGroup)
+    if (data->isReadAttribute)
     {
-        switch (data->clusterId)
+        // It should always enter here if isReadAttribute is true
+        if (binding.type == EMBER_UNICAST_BINDING && !data->isGroup)
         {
-        case Clusters::OnOff::Id:
-            ProcessOnOffGroupBindingCommand(data->commandId, binding);
-            break;
+            switch (data->clusterId)
+            {
+            case Clusters::Identify::Id:
+                ProcessIdentifyUnicastBindingRead(data, binding, peer_device);
+                break;
+            case Clusters::OnOff::Id:
+                ProcessOnOffUnicastBindingRead(data, binding, peer_device);
+                break;
+            case Clusters::LevelControl::Id:
+                ProcessLevelControlUnicastBindingRead(data, binding, peer_device);
+                break;
+            case Clusters::ColorControl::Id:
+                ProcessColorControlUnicastBindingRead(data, binding, peer_device);
+                break;
+            case Clusters::Thermostat::Id:
+                ProcessThermostatUnicastBindingRead(data, binding, peer_device);
+                break;
+            }
         }
     }
-    else if (binding.type == EMBER_UNICAST_BINDING && !data->isGroup)
+    else
     {
-        switch (data->clusterId)
+        if (binding.type == EMBER_MULTICAST_BINDING && data->isGroup)
         {
-        case Clusters::OnOff::Id:
-            ProcessOnOffUnicastBindingCommand(data->commandId, binding, peer_device);
-            break;
+            switch (data->clusterId)
+            {
+            case Clusters::Identify::Id:
+                ProcessIdentifyGroupBindingCommand(data, binding);
+                break;
+            case Clusters::OnOff::Id:
+                ProcessOnOffGroupBindingCommand(data, binding);
+                break;
+            case Clusters::LevelControl::Id:
+                ProcessColorControlGroupBindingCommand(data, binding);
+                break;
+            case Clusters::ColorControl::Id:
+                ProcessColorControlGroupBindingCommand(data, binding);
+                break;
+            case Clusters::Thermostat::Id:
+                ProcessThermostatGroupBindingCommand(data, binding);
+                break;
+            }
+        }
+        else if (binding.type == EMBER_UNICAST_BINDING && !data->isGroup)
+        {
+            switch (data->clusterId)
+            {
+            case Clusters::Identify::Id:
+                ProcessIdentifyUnicastBindingCommand(data, binding, peer_device);
+                break;
+            case Clusters::OnOff::Id:
+                ProcessOnOffUnicastBindingCommand(data, binding, peer_device);
+                break;
+            case Clusters::LevelControl::Id:
+                ProcessLevelControlUnicastBindingCommand(data, binding, peer_device);
+                break;
+            case Clusters::ColorControl::Id:
+                ProcessColorControlUnicastBindingCommand(data, binding, peer_device);
+                break;
+            case Clusters::Thermostat::Id:
+                ProcessThermostatUnicastBindingCommand(data, binding, peer_device);
+                break;
+            }
         }
     }
 }
@@ -149,7 +143,7 @@
     chip::BindingManager::GetInstance().RegisterBoundDeviceContextReleaseHandler(LightSwitchContextReleaseHandler);
 }
 
-#ifdef CONFIG_ENABLE_CHIP_SHELL
+#if CONFIG_ENABLE_CHIP_SHELL
 
 /********************************************************
  * Switch shell functions
@@ -172,56 +166,6 @@
 }
 
 /********************************************************
- * OnOff switch shell functions
- *********************************************************/
-
-CHIP_ERROR OnOffHelpHandler(int argc, char ** argv)
-{
-    sShellSwitchOnOffSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
-    return CHIP_NO_ERROR;
-}
-
-CHIP_ERROR OnOffSwitchCommandHandler(int argc, char ** argv)
-{
-    if (argc == 0)
-    {
-        return OnOffHelpHandler(argc, argv);
-    }
-
-    return sShellSwitchOnOffSubCommands.ExecCommand(argc, argv);
-}
-
-CHIP_ERROR OnSwitchCommandHandler(int argc, char ** argv)
-{
-    BindingCommandData * data = Platform::New<BindingCommandData>();
-    data->commandId           = Clusters::OnOff::Commands::On::Id;
-    data->clusterId           = Clusters::OnOff::Id;
-
-    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
-    return CHIP_NO_ERROR;
-}
-
-CHIP_ERROR OffSwitchCommandHandler(int argc, char ** argv)
-{
-    BindingCommandData * data = Platform::New<BindingCommandData>();
-    data->commandId           = Clusters::OnOff::Commands::Off::Id;
-    data->clusterId           = Clusters::OnOff::Id;
-
-    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
-    return CHIP_NO_ERROR;
-}
-
-CHIP_ERROR ToggleSwitchCommandHandler(int argc, char ** argv)
-{
-    BindingCommandData * data = Platform::New<BindingCommandData>();
-    data->commandId           = Clusters::OnOff::Commands::Toggle::Id;
-    data->clusterId           = Clusters::OnOff::Id;
-
-    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
-    return CHIP_NO_ERROR;
-}
-
-/********************************************************
  * bind switch shell functions
  *********************************************************/
 
@@ -292,59 +236,6 @@
     return sShellSwitchGroupsSubCommands.ExecCommand(argc, argv);
 }
 
-/********************************************************
- * Groups OnOff switch shell functions
- *********************************************************/
-
-CHIP_ERROR GroupsOnOffHelpHandler(int argc, char ** argv)
-{
-    sShellSwitchGroupsOnOffSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
-    return CHIP_NO_ERROR;
-}
-
-CHIP_ERROR GroupsOnOffSwitchCommandHandler(int argc, char ** argv)
-{
-    if (argc == 0)
-    {
-        return GroupsOnOffHelpHandler(argc, argv);
-    }
-
-    return sShellSwitchGroupsOnOffSubCommands.ExecCommand(argc, argv);
-}
-
-CHIP_ERROR GroupOnSwitchCommandHandler(int argc, char ** argv)
-{
-    BindingCommandData * data = Platform::New<BindingCommandData>();
-    data->commandId           = Clusters::OnOff::Commands::On::Id;
-    data->clusterId           = Clusters::OnOff::Id;
-    data->isGroup             = true;
-
-    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
-    return CHIP_NO_ERROR;
-}
-
-CHIP_ERROR GroupOffSwitchCommandHandler(int argc, char ** argv)
-{
-    BindingCommandData * data = Platform::New<BindingCommandData>();
-    data->commandId           = Clusters::OnOff::Commands::Off::Id;
-    data->clusterId           = Clusters::OnOff::Id;
-    data->isGroup             = true;
-
-    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
-    return CHIP_NO_ERROR;
-}
-
-CHIP_ERROR GroupToggleSwitchCommandHandler(int argc, char ** argv)
-{
-    BindingCommandData * data = Platform::New<BindingCommandData>();
-    data->commandId           = Clusters::OnOff::Commands::Toggle::Id;
-    data->clusterId           = Clusters::OnOff::Id;
-    data->isGroup             = true;
-
-    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
-    return CHIP_NO_ERROR;
-}
-
 /**
  * @brief configures switch matter shell
  *
@@ -354,27 +245,332 @@
 
     static const shell_command_t sSwitchSubCommands[] = {
         { &SwitchHelpHandler, "help", "Usage: switch <subcommand>" },
+        { &IdentifySwitchCommandHandler, "identify", " Usage: switch identify <subcommand>" },
         { &OnOffSwitchCommandHandler, "onoff", " Usage: switch onoff <subcommand>" },
+        { &LevelControlSwitchCommandHandler, "levelcontrol", " Usage: switch levlecontrol <subcommand>" },
+        { &ColorControlSwitchCommandHandler, "colorcontrol", " Usage: switch colorcontrol <subcommand>" },
+        { &ThermostatSwitchCommandHandler, "thermostat", " Usage: switch thermostat <subcommand>" },
         { &GroupsSwitchCommandHandler, "groups", "Usage: switch groups <subcommand>" },
         { &BindingSwitchCommandHandler, "binding", "Usage: switch binding <subcommand>" }
     };
 
-    static const shell_command_t sSwitchOnOffSubCommands[] = {
-        { &OnOffHelpHandler, "help", "Usage : switch ononff <subcommand>" },
-        { &OnSwitchCommandHandler, "on", "Sends on command to bound lighting app" },
-        { &OffSwitchCommandHandler, "off", "Sends off command to bound lighting app" },
-        { &ToggleSwitchCommandHandler, "toggle", "Sends toggle command to bound lighting app" }
+    static const shell_command_t sSwitchIdentifySubCommands[] = {
+        { &IdentifyHelpHandler, "help", "Usage: switch identify <subcommand>" },
+        { &IdentifyCommandHandler, "identify", "identify Usage: switch identify identify" },
+        { &TriggerEffectSwitchCommandHandler, "triggereffect", "triggereffect Usage: switch identify triggereffect" },
+        { &IdentifyRead, "read", "Usage : switch identify read <attribute>" }
     };
 
-    static const shell_command_t sSwitchGroupsSubCommands[] = { { &GroupsHelpHandler, "help", "Usage: switch groups <subcommand>" },
-                                                                { &GroupsOnOffSwitchCommandHandler, "onoff",
-                                                                  "Usage: switch groups onoff <subcommand>" } };
+    static const shell_command_t sSwitchIdentifyReadSubCommands[] = {
+        { &IdentifyReadHelpHandler, "help", "Usage : switch identify read <attribute>" },
+        { &IdentifyReadAttributeList, "attlist", "Read attribute list" },
+        { &IdentifyReadIdentifyTime, "identifytime", "Read identifytime attribute" },
+        { &IdentifyReadIdentifyType, "identifytype", "Read identifytype attribute" },
+    };
+
+    static const shell_command_t sSwitchOnOffSubCommands[] = {
+        { &OnOffHelpHandler, "help", "Usage: switch ononff <subcommand>" },
+        { &OnSwitchCommandHandler, "on", "on Usage: switch onoff on" },
+        { &OffSwitchCommandHandler, "off", "off Usage: switch onoff off" },
+        { &ToggleSwitchCommandHandler, "toggle", "toggle Usage: switch onoff toggle" },
+        { &OffWithEffectSwitchCommandHandler, "offWE", "off-with-effect Usage: switch onoff offWE <EffectId> <EffectVariant>" },
+        { &OnWithRecallGlobalSceneSwitchCommandHandler, "onWRGS", "on-with-recall-global-scene Usage: switch onoff onWRGS" },
+        { &OnWithTimedOffSwitchCommandHandler, "onWTO",
+          "on-with-timed-off Usage: switch onoff onWTO <OnOffControl> <OnTime> <OffWaitTime>" },
+        { &OnOffRead, "read", "Usage : switch onoff read <attribute>" }
+    };
+
+    static const shell_command_t sSwitchOnOffReadSubCommands[] = {
+        { &OnOffReadHelpHandler, "help", "Usage : switch ononff read <attribute>" },
+        { &OnOffReadAttributeList, "attlist", "Read attribute list" },
+        { &OnOffReadOnOff, "onoff", "Read onoff attribute" },
+        { &OnOffReadGlobalSceneControl, "GSC", "Read GlobalSceneControl attribute" },
+        { &OnOffReadOnTime, "ontime", "Read ontime attribute" },
+        { &OnOffReadOffWaitTime, "offwaittime", "Read offwaittime attribute" },
+        { &OnOffReadStartUpOnOff, "SOO", "Read startuponoff attribute" },
+    };
+
+    static const shell_command_t sSwitchLevelControlSubCommands[] = {
+        { &LevelControlHelpHandler, "help", "Usage: switch levelcontrol <subcommand>" },
+        { &MoveToLevelSwitchCommandHandler, "movetolevel",
+          "movetolevel Usage: switch levelcontrol movetolevel <level> <transitiontime> <optionsmask> <optionsoverride>" },
+        { &MoveSwitchCommandHandler, "move",
+          "move Usage: switch levelcontrol move <movemode> <rate> <optionsmask> <optionsoverride>" },
+        { &StepSwitchCommandHandler, "step",
+          "step Usage: switch levelcontrol step <stepmode> <stepsize> <transitiontime> <optionsmask> <optionsoverride>" },
+        { &StopSwitchCommandHandler, "stop", "step Usage: switch levelcontrol stop <optionsmask> <optionsoverride>" },
+        { &MoveToLevelWithOnOffSwitchCommandHandler, "MTLWOO",
+          "movetolevelwithonoff Usage: switch levelcontrol MTLWOO <level> <transitiontime> <optionsmask> <optionsoverride>" },
+        { &MoveWithOnOffSwitchCommandHandler, "MWOO",
+          "movewithonoff Usage: switch levelcontrol MWOO <movemode> <rate> <optionsmask> <optionsoverride>" },
+        { &StepWithOnOffSwitchCommandHandler, "stepWOO",
+          "stepwithonoff Usage: switch levelcontrol stepWOO <stepmode> <stepsize> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &StopWithOnOffSwitchCommandHandler, "stopWOO",
+          "stopwithonoff Usage: switch levelcontrol stopWOO <optionsmask> <optionsoverride>" },
+        { &LevelControlRead, "read", "Usage : switch levelcontrol read <attribute>" }
+    };
+
+    static const shell_command_t sSwitchLevelControlReadSubCommands[] = {
+        { &LevelControlReadHelpHandler, "help", "Usage : switch levelcontrol read <attribute>" },
+        { &LevelControlReadAttributeList, "attlist", "Read attribute list" },
+        { &LevelControlReadCurrentLevel, "currentlevel", "Read currentlevel attribute" },
+        { &LevelControlReadRemainingTime, "remainingtime", "Read remainingtime attribute" },
+        { &LevelControlReadMinLevel, "minlevel", "Read minlevel attribute" },
+        { &LevelControlReadMaxLevel, "maxlevel", "Read maxlevel attribute" },
+        { &LevelControlReadCurrentFrequency, "currentfrequency", "Read currentfrequency attribute" },
+        { &LevelControlReadMinFrequency, "minfrequency", "Read minfrequency attribute" },
+        { &LevelControlReadMaxFrequency, "maxfrequency", "Read maxfrequency attribute" },
+        { &LevelControlReadOptions, "options", "Read options attribute" },
+        { &LevelControlReadOnOffTransitionTime, "OOTT", "Read onofftransitiontime attribute" },
+        { &LevelControlReadOnLevel, "onlevel", "Read onlevel attribute" },
+        { &LevelControlReadOnTransitionTime, "OnTT", "Read ontransitiontime attribute" },
+        { &LevelControlReadOffTransitionTime, "OffTT", "Read offtransitiontime attribute" },
+        { &LevelControlReadDefaultMoveRate, "DMR", "Read defaultmoverate attribute" },
+        { &LevelControlReadStartUpCurrentLevel, "SUCL", "Read startupcurrentlevel attribute" },
+    };
+
+    static const shell_command_t sSwitchColorControlSubCommands[] = {
+        { &ColorControlHelpHandler, "help", "Usage: switch colorcontrol <subcommand>" },
+        { &MoveToHueCommandHandler, "movetohue",
+          "movetohue Usage: switch colorcontrol movetohue <hue> <direction> <transitiontime> <optionsmask> <optionsoverride>" },
+        { &MoveHueCommandHandler, "movehue",
+          "movehue Usage: switch colorcontrol movehue <movemode> <rate> <optionsmask> <optionsoverride>" },
+        { &StepHueCommandHandler, "stephue",
+          "stephue Usage: switch colorcontrol stephue <stepmode> <stepsize> <transitiontime> <optionsmask> <optionsoverride>" },
+        { &MoveToSaturationCommandHandler, "movetosat",
+          "movetosaturation Usage: switch colorcontrol movetosat <saturation> <transitiontime> <optionsmask> <optionsoverride>" },
+        { &MoveSaturationCommandHandler, "movesat",
+          "movesaturation Usage: switch colorcontrol movesat <movemode> <rate> <optionsmask> <optionsoverride>" },
+        { &StepSaturationCommandHandler, "stepsat",
+          "stepsaturation Usage: switch colorcontrol stepsat <stepmode> <stepsize> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &MoveToHueAndSaturationCommandHandler, "movetoHS",
+          "movetohueandsaturation Usage: switch colorcontrol movetoHS <hue> <saturation> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &MoveToColorCommandHandler, "movetocolor",
+          "movetocolor Usage: switch colorcontrol movetocolor <colorx> <colory> <transitiontime> <optionsmask> <optionsoverride>" },
+        { &MoveColorCommandHandler, "movecolor",
+          "movecolor Usage: switch colorcontrol movecolor <ratex> <ratey> <optionsmask> <optionsoverride>" },
+        { &StepColorCommandHandler, "stepcolor",
+          "stepcolor Usage: switch colorcontrol stepcolor <stepx> <stepy> <transitiontime> <optionsmask> <optionsoverride>" },
+        { &MoveToColorTemperatureCommandHandler, "movetoCT",
+          "movetocolortemperature Usage: switch colorcontrol movetoCT <colortempmireds> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &EnhancedMoveToHueCommandHandler, "Emovetohue",
+          "enhancedmovetohue Usage: switch colorcontrol Emovetohue <enhancedhue> <direction> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &EnhancedMoveHueCommandHandler, "Emovehue",
+          "enhancedmovehue Usage: switch colorcontrol Emovehue <movemode> <rate> <optionsmask> <optionsoverride>" },
+        { &EnhancedStepHueCommandHandler, "Estephue",
+          "enhancedstephue Usage: switch colorcontrol Estephue <stepmode> <stepsize> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &EnhancedMoveToHueAndSaturationCommandHandler, "EmovetoHS",
+          "enhancedmovetohueandsaturation Usage: switch colorcontrol EmovetoHS <enhancedhue> <saturation> <transitiontime> "
+          "<optionsmask> <optionsoverride>" },
+        { &ColorLoopSetCommandHandler, "colorloopset",
+          "colorloopset Usage: switch colorcontrol colorloopset <updateflags> <action> <direction> <time> <starhue> <optionsmask> "
+          "<optionsoverride>" },
+        { &StopMoveStepCommandHandler, "stopmovestep",
+          "stopmovestep Usage: switch colorcontrol stopmovestep <optionsmask> <optionsoverride>" },
+        { &MoveColorTemperatureCommandHandler, "moveCT",
+          "movecolortemperature Usage: switch colorcontrol moveCT <movemode> <rate> <colortempminmireds> <colortempmaxmireds> "
+          "<optionsmask> <optionsoverride>" },
+        { &StepColorTemperatureCommandHandler, "stepCT",
+          "stepcolortemperature Usage: switch colorcontrol stepCT <stepmode> <stepsize> <transitiontime> <colortempminmireds> "
+          "<colortempmaxmireds> <optionsmask> <optionsoverride>" },
+        { &ColorControlRead, "read", "Usage : switch colorcontrol read <attribute>" }
+    };
+
+    static const shell_command_t sSwitchColorControlReadSubCommands[] = {
+        // fill in read color control attributes commands
+        { &ColorControlReadHelpHandler, "help", "Usage : switch colorcontrol read <attribute>" },
+        { &ColorControlReadAttributeList, "attlist", "Read attribute list" },
+        { &ColorControlReadCurrentHue, "currenthue", "Read currenthue attribute" },
+        { &ColorControlReadCurrentSaturation, "currentsat", "Read currentsaturaion attribute" },
+        { &ColorControlReadRemainingTime, "remaintime", "Read remainingtime attribute" },
+        { &ColorControlReadCurrentX, "current-x", "Read current-x attribute" },
+        { &ColorControlReadCurrentY, "current-y", "Read current-y attribute" },
+        { &ColorControlReadDriftCompensation, "driftcomp", "Read driftcompensation attribute" },
+        { &ColorControlReadCompensationText, "comptext", "Read compensationtext attribute" },
+        { &ColorControlReadColorTemperature, "colortemp", "Read colortemperature attribute" },
+        { &ColorControlReadColorMode, "colormode", "Read colormode attribute" },
+        { &ColorControlReadOptions, "options", "Read options attribute" },
+        { &ColorControlReadNumberOfPrimaries, "noofprimaries", "Read numberofprimaries attribute" },
+        { &ColorControlReadPrimary1X, "primary1x", "Read primary1x attribute" },
+        { &ColorControlReadPrimary1Y, "primary1y", "Read primary1y attribute" },
+        { &ColorControlReadPrimary1Intensity, "primary1intensity", "Read primary1intensity attribute" },
+        { &ColorControlReadPrimary2X, "primary2x", "Read primary2x attribute" },
+        { &ColorControlReadPrimary2Y, "primary2y", "Read primary2y attribute" },
+        { &ColorControlReadPrimary2Intensity, "primary2intensity", "Read primary2intensity attribute" },
+        { &ColorControlReadPrimary3X, "primary3x", "Read primary3x attribute" },
+        { &ColorControlReadPrimary3Y, "primary3y", "Read primary3y attribute" },
+        { &ColorControlReadPrimary3Intensity, "primary3intensity", "Read primary3intensity attribute" },
+        { &ColorControlReadPrimary4X, "primary4x", "Read primary4x attribute" },
+        { &ColorControlReadPrimary4Y, "primary4y", "Read primary4y attribute" },
+        { &ColorControlReadPrimary4Intensity, "primary4intensity", "Read primary4intensity attribute" },
+        { &ColorControlReadPrimary5X, "primary5x", "Read primary5x attribute" },
+        { &ColorControlReadPrimary5Y, "primary5y", "Read primary5y attribute" },
+        { &ColorControlReadPrimary5Intensity, "primary5intensity", "Read primary5intensity attribute" },
+        { &ColorControlReadPrimary6X, "primary6x", "Read primary6x attribute" },
+        { &ColorControlReadPrimary6Y, "primary6y", "Read primary6y attribute" },
+        { &ColorControlReadPrimary6Intensity, "primary6intensity", "Read primary6intensity attribute" },
+        { &ColorControlReadWhitePointX, "whitepointx", "Read whitepointx attribute" },
+        { &ColorControlReadWhitePointY, "whitepointy", "Read whitepointy attribute" },
+        { &ColorControlReadColorPointRX, "colorpointrx", "Read colorpointrx attribute" },
+        { &ColorControlReadColorPointRY, "colorpointry", "Read colorpointry attribute" },
+        { &ColorControlReadColorPointRIntensity, "colorpointrintensity", "Read colorpointrintensity attribute" },
+        { &ColorControlReadColorPointGX, "colorpointgx", "Read colorpointgx attribute" },
+        { &ColorControlReadColorPointGY, "colorpointgy", "Read colorpointgy attribute" },
+        { &ColorControlReadColorPointGIntensity, "colorpointgintensity", "Read colorpointgintensity attribute" },
+        { &ColorControlReadColorPointBX, "colorpointbx", "Read colorpointbx attribute" },
+        { &ColorControlReadColorPointBY, "colorpointby", "Read colorpointby attribute" },
+        { &ColorControlReadColorPointBIntensity, "colorpointbintensity", "Read colorpointbintensity attribute" },
+        { &ColorControlReadEnhancedCurrentHue, "Ecurrenthue", "Read enhancedcurrenthue attribute" },
+        { &ColorControlReadEnhancedColorMode, "Ecolormode", "Read enhancedcolormode attribute" },
+        { &ColorControlReadColorLoopActive, "colorloopactive", "Read colorloopactive attribute" },
+        { &ColorControlReadColorLoopDirection, "colorloopdirection", "Read colorloopdirection attribute" },
+        { &ColorControlReadColorLoopTime, "colorlooptime", "Read colorlooptime attribute" },
+        { &ColorControlReadColorLoopStartEnhancedHue, "colorloopstartenhancedhue", "Read colorloopstartenhancedHue attribute" },
+        { &ColorControlReadColorLoopStoredEnhancedHue, "colorloopstoredenhancedhue", "Read colorloopstoredenhancedHue attribute" },
+        { &ColorControlReadColorCapabilities, "colorcapabilities", "Read colorcapabilities attribute" },
+        { &ColorControlReadColorTempPhysicalMinMireds, "colortempphyminmireds", "Read colortempphysicalminmireds attribute" },
+        { &ColorControlReadColorTempPhysicalMaxMireds, "colortempphymaxmireds", "Read colortempphysicalmaxmireds attribute" },
+        { &ColorControlReadCoupleColorTempToLevelMinMireds, "CCTTMM", "Read couplecolortemptolevelminmireds attribute" },
+        { &ColorControlReadStartUpColorTemperatureMireds, "SUCTM", "Read startupcolortempmireds attribute" },
+    };
+
+    static const shell_command_t sSwitchThermostatSubCommands[] = {
+        { &ThermostatHelpHandler, "help", "Usage: switch thermostat <subcommand>" },
+        { &SetpointRaiseLowerSwitchCommandHandler, "SPRL", "setpointraiselower Usage: switch thermostat SPRL <mode> <amount>" },
+        { &ThermostatRead, "read", "Usage : switch thermostat read <attribute>" }
+    };
+
+    static const shell_command_t sSwitchThermostatReadSubCommands[] = {
+        { &ThermostatReadHelpHandler, "help", "Usage : switch thermostat read <attribute>" },
+        { &ThermostatReadAttributeList, "attlist", "Read attribute list" },
+        { &ThermostatReadLocalTemperature, "localtemp", "Read localtemperature attribute" },
+        { &ThermostatReadAbsMinHeatSetpointLimit, "absminHSL", "Read absminheatsetpointlimit attribute" },
+        { &ThermostatReadAbsMaxHeatSetpointLimit, "absmaxHSL", "Read absmaxheatsetpointlimit attribute" },
+        { &ThermostatReadAbsMinCoolSetpointLimit, "absminCSL", "Read absmincoolsetpointlimit attribute" },
+        { &ThermostatReadAbsMaxCoolSetpointLimit, "absmaxCSL", "Read absmaxcoolsetpointlimit attribute" },
+        { &ThermostatReadPiCoolingDemand, "picoolingdemand", "Read picoolingdemand attribute" },
+        { &ThermostatReadPiHeatingDemand, "piheatingdemand", "Read piheatingdemand attribute" },
+        { &ThermostatReadOccupiedCoolingSetpoint, "OCS", "Read occupiedcoolingsetpoint attribute" },
+        { &ThermostatReadOccupiedHeatingSetpoint, "OHS", "Read occupiedheatingsetpoint attribute" },
+        { &ThermostatReadMinHeatSetpointLimit, "minHSL", "Read minheatsetpointlimit attribute" },
+        { &ThermostatReadMaxHeatSetpointLimit, "maxHSL", "Read maxheatsetpointlimit attribute" },
+        { &ThermostatReadMinCoolSetpointLimit, "minCSL", "Read mincoolsetpointlimit attribute" },
+        { &ThermostatReadMaxCoolSetpointLimit, "maxCSL", "Read maxcoolsetpointlimit attribute" },
+        { &ThermostatReadControlSequenceOfOperation, "CSOP", "Read controlsequenceofoperation attribute" },
+        { &ThermostatReadSystemMode, "systemmode", "Read systemmode attribute" },
+    };
+
+    static const shell_command_t sSwitchGroupsSubCommands[] = {
+        { &GroupsHelpHandler, "help", "Usage: switch groups <subcommand>" },
+        { &GroupsOnOffSwitchCommandHandler, "onoff", "Usage: switch groups onoff <subcommand>" },
+        { &GroupsLevelControlSwitchCommandHandler, "levelcontrol", "Usage: switch groups levelcontrol <subcommand>" },
+        { &GroupsColorControlSwitchCommandHandler, "colorcontrol", "Usage: switch groups colorcontrol <subcommand>" },
+        { &GroupsThermostatSwitchCommandHandler, "thermostat", "Usage: switch groups thermostat <subcommand>" },
+    };
+
+    static const shell_command_t sSwitchGroupsIdentifySubCommands[] = {
+        { &GroupsIdentifyHelpHandler, "help", "Usage: switch groups onoff <subcommand>" },
+        { &GroupIdentifyCommandHandler, "identify", "Sends identify command to bound group" },
+        { &GroupTriggerEffectSwitchCommandHandler, "triggereffect", "Sends triggereffect command to group" },
+    };
 
     static const shell_command_t sSwitchGroupsOnOffSubCommands[] = {
         { &GroupsOnOffHelpHandler, "help", "Usage: switch groups onoff <subcommand>" },
         { &GroupOnSwitchCommandHandler, "on", "Sends on command to bound group" },
         { &GroupOffSwitchCommandHandler, "off", "Sends off command to bound group" },
-        { &GroupToggleSwitchCommandHandler, "toggle", "Sends toggle command to group" }
+        { &GroupToggleSwitchCommandHandler, "toggle", "Sends toggle command to group" },
+        { &GroupOffWithEffectSwitchCommandHandler, "offWE", "Sends off-with-effect command to group" },
+        { &GroupOnWithRecallGlobalSceneSwitchCommandHandler, "onWRGS", "Sends on-with-recall-global-scene command to group" },
+        { &GroupOnWithTimedOffSwitchCommandHandler, "onWTO", "Sends on-with-timed-off command to group" }
+    };
+
+    static const shell_command_t sSwitchGroupsLevelControlSubCommands[] = {
+        { &GroupsLevelControlHelpHandler, "help", "Usage: switch groupos levelcontrol <subcommand>" },
+        { &GroupsMoveToLevelSwitchCommandHandler, "movetolevel",
+          "movetolevel Usage: switch groups levelcontrol movetolevel <level> <transitiontime> <optionsmask> <optionsoverride>" },
+        { &GroupsMoveSwitchCommandHandler, "move",
+          "move Usage: switch groups levelcontrol move <movemode> <rate> <optionsmask> <optionsoverride>" },
+        { &GroupsStepSwitchCommandHandler, "step",
+          "step Usage: switch groups levelcontrol step <stepmode> <stepsize> <transitiontime> <optionsmask> <optionsoverride>" },
+        { &GroupsStopSwitchCommandHandler, "stop", "step Usage: switch groups levelcontrol stop <optionsmask> <optionsoverride>" },
+        { &GroupsMoveToLevelWithOnOffSwitchCommandHandler, "MTLWOO",
+          "movetolevelwithonoff Usage: switch groups levelcontrol MTLWOO <level> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &GroupsMoveWithOnOffSwitchCommandHandler, "MWOO",
+          "movewithonoff Usage: switch groups levelcontrol MWOO <movemode> <rate> <optionsmask> <optionsoverride>" },
+        { &GroupsStepWithOnOffSwitchCommandHandler, "stepWOO",
+          "stepwithonoff Usage: switch groups levelcontrol stepWOO <stepmode> <stepsize> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &GroupsStopWithOnOffSwitchCommandHandler, "stopWOO",
+          "stopwithonoff Usage: switch groups levelcontrol stopWOO <optionsmask> <optionsoverride>" },
+    };
+
+    static const shell_command_t sSwitchGroupsColorControlSubCommands[] = {
+        { &GroupsColorControlHelpHandler, "help", "Usage: switch groups colorcontrol <subcommand>" },
+        { &GroupsMoveToHueCommandHandler, "movetohue",
+          "movetohue Usage: switch groups colorcontrol movetohue <hue> <direction> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &GroupsMoveHueCommandHandler, "movehue",
+          "movehue Usage: switch groups colorcontrol movehue <movemode> <rate> <optionsmask> <optionsoverride>" },
+        { &GroupsStepHueCommandHandler, "stephue",
+          "stephue Usage: switch groups colorcontrol stephue <stepmode> <stepsize> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &GroupsMoveToSaturationCommandHandler, "movetosat",
+          "movetosaturation Usage: switch groups colorcontrol movetosat <saturation> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &GroupsMoveSaturationCommandHandler, "movesat",
+          "movesaturation Usage: switch groups colorcontrol movesat <movemode> <rate> <optionsmask> <optionsoverride>" },
+        { &GroupsStepSaturationCommandHandler, "stepsat",
+          "stepsaturation Usage: switch groups colorcontrol stepsat <stepmode> <stepsize> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &GroupsMoveToHueAndSaturationCommandHandler, "movetoHS",
+          "movetohueandsaturation Usage: switch groups colorcontrol movetoHS <hue> <saturation> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &GroupsMoveToColorCommandHandler, "movetocolor",
+          "movetocolor Usage: switch groups colorcontrol movetocolor <colorx> <colory> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &GroupsMoveColorCommandHandler, "movecolor",
+          "movecolor Usage: switch groups colorcontrol movecolor <ratex> <ratey> <optionsmask> <optionsoverride>" },
+        { &GroupsStepColorCommandHandler, "stepcolor",
+          "stepcolor Usage: switch groups colorcontrol stepcolor <stepx> <stepy> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &GroupsMoveToColorTemperatureCommandHandler, "movetoCT",
+          "movetocolortemperature Usage: switch groups colorcontrol movetoCT <colortempmireds> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &GroupsEnhancedMoveToHueCommandHandler, "Emovetohue",
+          "enhancedmovetohue Usage: switch groups colorcontrol Emovetohue <enhancedhue> <direction> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &GroupsEnhancedMoveHueCommandHandler, "Emovehue",
+          "enhancedmovehue Usage: switch groups colorcontrol Emovehue <movemode> <rate> <optionsmask> <optionsoverride>" },
+        { &GroupsEnhancedStepHueCommandHandler, "Estephue",
+          "enhancedstephue Usage: switch gropus colorcontrol Estephue <stepmode> <stepsize> <transitiontime> <optionsmask> "
+          "<optionsoverride>" },
+        { &GroupsEnhancedMoveToHueAndSaturationCommandHandler, "EmovetoHS",
+          "enhancedmovetohueandsaturation Usage: switch groups colorcontrol EmovetoHS <enhancedhue> <saturation> <transitiontime> "
+          "<optionsmask> <optionsoverride>" },
+        { &GroupsColorLoopSetCommandHandler, "colorloopset",
+          "colorloopset Usage: switch groups colorcontrol colorloopset <updateflags> <action> <direction> <time> <starhue> "
+          "<optionsmask> <optionsoverride>" },
+        { &GroupsStopMoveStepCommandHandler, "stopmovestep",
+          "stopmovestep Usage: switch groups colorcontrol stopmovestep <optionsmask> <optionsoverride>" },
+        { &GroupsMoveColorTemperatureCommandHandler, "moveCT",
+          "movecolortemperature Usage: switch groups colorcontrol moveCT <movemode> <rate> <colortempminmireds> "
+          "<colortempmaxmireds> <optionsmask> <optionsoverride>" },
+        { &GroupsStepColorTemperatureCommandHandler, "stepCT",
+          "stepcolortemperature Usage: switch groups colorcontrol stepCT <stepmode> <stepsize> <transitiontime> "
+          "<colortempminmireds> <colortempmaxmireds> <optionsmask> <optionsoverride>" },
+    };
+
+    static const shell_command_t sSwitchGroupsThermostatSubCommands[] = {
+        { &GroupsThermostatHelpHandler, "help", "Usage: switch groups thermostat <subcommand>" },
+        { &GroupsSetpointRaiseLowerSwitchCommandHandler, "SPRL",
+          "setpointraiselower Usage: switch groups thermostat SPRL <mode> <amount>" },
     };
 
     static const shell_command_t sSwitchBindingSubCommands[] = {
@@ -386,8 +582,31 @@
     static const shell_command_t sSwitchCommand = { &SwitchCommandHandler, "switch",
                                                     "Light-switch commands. Usage: switch <subcommand>" };
 
+    // Register groups command
+    sShellSwitchGroupsIdentifySubCommands.RegisterCommands(sSwitchGroupsIdentifySubCommands,
+                                                           ArraySize(sSwitchGroupsIdentifySubCommands));
     sShellSwitchGroupsOnOffSubCommands.RegisterCommands(sSwitchGroupsOnOffSubCommands, ArraySize(sSwitchGroupsOnOffSubCommands));
+    sShellSwitchGroupsLevelControlSubCommands.RegisterCommands(sSwitchGroupsLevelControlSubCommands,
+                                                               ArraySize(sSwitchGroupsLevelControlSubCommands));
+    sShellSwitchGroupsColorControlSubCommands.RegisterCommands(sSwitchGroupsColorControlSubCommands,
+                                                               ArraySize(sSwitchGroupsColorControlSubCommands));
+    sShellSwitchGroupsThermostatSubCommands.RegisterCommands(sSwitchGroupsThermostatSubCommands,
+                                                             ArraySize(sSwitchGroupsThermostatSubCommands));
+
+    // Register commands
+    sShellSwitchIdentifySubCommands.RegisterCommands(sSwitchIdentifySubCommands, ArraySize(sSwitchIdentifySubCommands));
+    sShellSwitchIdentifyReadSubCommands.RegisterCommands(sSwitchIdentifyReadSubCommands, ArraySize(sSwitchIdentifyReadSubCommands));
     sShellSwitchOnOffSubCommands.RegisterCommands(sSwitchOnOffSubCommands, ArraySize(sSwitchOnOffSubCommands));
+    sShellSwitchOnOffReadSubCommands.RegisterCommands(sSwitchOnOffReadSubCommands, ArraySize(sSwitchOnOffReadSubCommands));
+    sShellSwitchLevelControlSubCommands.RegisterCommands(sSwitchLevelControlSubCommands, ArraySize(sSwitchLevelControlSubCommands));
+    sShellSwitchLevelControlReadSubCommands.RegisterCommands(sSwitchLevelControlReadSubCommands,
+                                                             ArraySize(sSwitchLevelControlReadSubCommands));
+    sShellSwitchColorControlSubCommands.RegisterCommands(sSwitchColorControlSubCommands, ArraySize(sSwitchColorControlSubCommands));
+    sShellSwitchColorControlReadSubCommands.RegisterCommands(sSwitchColorControlReadSubCommands,
+                                                             ArraySize(sSwitchColorControlReadSubCommands));
+    sShellSwitchThermostatSubCommands.RegisterCommands(sSwitchThermostatSubCommands, ArraySize(sSwitchThermostatSubCommands));
+    sShellSwitchThermostatReadSubCommands.RegisterCommands(sSwitchThermostatReadSubCommands,
+                                                           ArraySize(sSwitchThermostatReadSubCommands));
     sShellSwitchGroupsSubCommands.RegisterCommands(sSwitchGroupsSubCommands, ArraySize(sSwitchGroupsSubCommands));
     sShellSwitchBindingSubCommands.RegisterCommands(sSwitchBindingSubCommands, ArraySize(sSwitchBindingSubCommands));
     sShellSwitchSubCommands.RegisterCommands(sSwitchSubCommands, ArraySize(sSwitchSubCommands));
diff --git a/examples/all-clusters-app/ameba/main/include/BindingHandler.h b/examples/all-clusters-app/ameba/main/include/BindingHandler.h
index 280c948..6df4285 100644
--- a/examples/all-clusters-app/ameba/main/include/BindingHandler.h
+++ b/examples/all-clusters-app/ameba/main/include/BindingHandler.h
@@ -18,6 +18,7 @@
 
 #pragma once
 
+#include "app-common/zap-generated/ids/Attributes.h"
 #include "app-common/zap-generated/ids/Clusters.h"
 #include "app-common/zap-generated/ids/Commands.h"
 #include "lib/core/CHIPError.h"
@@ -28,8 +29,11 @@
 
 struct BindingCommandData
 {
+    chip::AttributeId attributeId;
     chip::EndpointId localEndpointId = 1;
     chip::CommandId commandId;
     chip::ClusterId clusterId;
-    bool isGroup = false;
+    bool isGroup         = false;
+    bool isReadAttribute = false;
+    uint32_t args[7];
 };
diff --git a/examples/all-clusters-app/ameba/main/include/ColorControlCommands.h b/examples/all-clusters-app/ameba/main/include/ColorControlCommands.h
new file mode 100644
index 0000000..f451447
--- /dev/null
+++ b/examples/all-clusters-app/ameba/main/include/ColorControlCommands.h
@@ -0,0 +1,2159 @@
+/*
+ *
+ *    Copyright (c) 2022 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include "controller/InvokeInteraction.h"
+#include "controller/ReadInteraction.h"
+#include <app/clusters/bindings/bindings.h>
+
+#if CONFIG_ENABLE_CHIP_SHELL
+#include "lib/shell/Engine.h"
+#include "lib/shell/commands/Help.h"
+#endif // ENABLE_CHIP_SHELL
+
+using namespace chip;
+using namespace chip::app;
+
+#if CONFIG_ENABLE_CHIP_SHELL
+using Shell::Engine;
+using Shell::shell_command_t;
+using Shell::streamer_get;
+using Shell::streamer_printf;
+
+Engine sShellSwitchColorControlSubCommands;
+Engine sShellSwitchColorControlReadSubCommands;
+Engine sShellSwitchGroupsColorControlSubCommands;
+#endif // defined(ENABLE_CHIP_SHELL)
+
+void ProcessColorControlUnicastBindingRead(BindingCommandData * data, const EmberBindingTableEntry & binding,
+                                           OperationalDeviceProxy * peer_device)
+{
+    auto onSuccess = [](const ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
+        ChipLogProgress(NotSpecified, "Read ColorControl attribute succeeds");
+    };
+
+    auto onFailure = [](const ConcreteDataAttributePath * attributePath, CHIP_ERROR error) {
+        ChipLogError(NotSpecified, "Read ColorControl attribute failed: %" CHIP_ERROR_FORMAT, error.Format());
+    };
+
+    VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady());
+
+    switch (data->attributeId)
+    {
+    case Clusters::ColorControl::Attributes::AttributeList::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::AttributeList::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::CurrentHue::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::CurrentHue::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::CurrentSaturation::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::CurrentSaturation::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::RemainingTime::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::RemainingTime::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::CurrentX::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::CurrentX::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::CurrentY::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::CurrentY::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::DriftCompensation::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::DriftCompensation::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::CompensationText::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::CompensationText::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorTemperatureMireds::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorTemperatureMireds::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorMode::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorMode::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Options::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Options::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::NumberOfPrimaries::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::NumberOfPrimaries::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary1X::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary1X::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary1Y::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary1Y::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary1Intensity::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary1Intensity::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary2X::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary2X::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary2Y::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary2Y::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary2Intensity::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary2Intensity::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary3X::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary3X::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary3Y::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary3Y::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary3Intensity::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary3Intensity::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary4X::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary4X::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary4Y::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary4Y::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary4Intensity::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary4Intensity::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary5X::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary5X::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary5Y::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary5Y::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary5Intensity::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary5Intensity::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary6X::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary6X::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary6Y::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary6Y::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::Primary6Intensity::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::Primary6Intensity::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::WhitePointX::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::WhitePointX::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::WhitePointY::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::WhitePointY::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorPointRX::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorPointRX::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorPointRY::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorPointRY::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorPointRIntensity::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorPointRIntensity::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorPointGX::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorPointGX::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorPointGY::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorPointGY::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorPointGIntensity::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorPointGIntensity::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorPointBX::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorPointBX::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorPointBY::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorPointBY::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorPointBIntensity::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorPointBIntensity::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::EnhancedCurrentHue::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::EnhancedCurrentHue::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::EnhancedColorMode::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::EnhancedColorMode::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorLoopActive::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorLoopActive::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorLoopDirection::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorLoopDirection::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorLoopTime::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorLoopTime::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorLoopStartEnhancedHue::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorLoopStartEnhancedHue::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorLoopStoredEnhancedHue::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorLoopStoredEnhancedHue::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorCapabilities::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorCapabilities::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorTempPhysicalMinMireds::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorTempPhysicalMinMireds::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::ColorTempPhysicalMaxMireds::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::ColorTempPhysicalMaxMireds::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::CoupleColorTempToLevelMinMireds::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::CoupleColorTempToLevelMinMireds::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Attributes::StartUpColorTemperatureMireds::Id:
+        Controller::ReadAttribute<Clusters::ColorControl::Attributes::StartUpColorTemperatureMireds::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+    }
+}
+
+void ProcessColorControlUnicastBindingCommand(BindingCommandData * data, const EmberBindingTableEntry & binding,
+                                              OperationalDeviceProxy * peer_device)
+{
+    auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) {
+        ChipLogProgress(NotSpecified, "ColorControl command succeeds");
+    };
+
+    auto onFailure = [](CHIP_ERROR error) {
+        ChipLogError(NotSpecified, "ColorControl command failed: %" CHIP_ERROR_FORMAT, error.Format());
+    };
+
+    VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady());
+
+    Clusters::ColorControl::Commands::MoveToHue::Type moveToHueCommand;
+    Clusters::ColorControl::Commands::MoveHue::Type moveHueCommand;
+    Clusters::ColorControl::Commands::StepHue::Type stepHueCommand;
+    Clusters::ColorControl::Commands::MoveToSaturation::Type moveToSaturationCommand;
+    Clusters::ColorControl::Commands::MoveSaturation::Type moveSaturationCommand;
+    Clusters::ColorControl::Commands::StepSaturation::Type stepSaturationCommand;
+    Clusters::ColorControl::Commands::MoveToHueAndSaturation::Type moveToHueAndSaturationCommand;
+    Clusters::ColorControl::Commands::MoveToColor::Type moveToColorCommand;
+    Clusters::ColorControl::Commands::MoveColor::Type moveColorCommand;
+    Clusters::ColorControl::Commands::StepColor::Type stepColorCommand;
+    Clusters::ColorControl::Commands::MoveToColorTemperature::Type moveToColorTemperatureCommand;
+    Clusters::ColorControl::Commands::EnhancedMoveToHue::Type enhancedMoveToHueCommand;
+    Clusters::ColorControl::Commands::EnhancedMoveHue::Type enhancedMoveHueCommand;
+    Clusters::ColorControl::Commands::EnhancedStepHue::Type enhancedStepHueCommand;
+    Clusters::ColorControl::Commands::EnhancedMoveToHueAndSaturation::Type enhancedMoveToHueAndSaturationCommand;
+    Clusters::ColorControl::Commands::ColorLoopSet::Type colorLoopSetCommand;
+    Clusters::ColorControl::Commands::StopMoveStep::Type stopMoveStepCommand;
+    Clusters::ColorControl::Commands::MoveColorTemperature::Type moveColorTemperatureCommand;
+    Clusters::ColorControl::Commands::StepColorTemperature::Type stepColorTemperatureCommand;
+
+    switch (data->commandId)
+    {
+    case Clusters::ColorControl::Commands::MoveToHue::Id:
+        moveToHueCommand.hue             = static_cast<uint8_t>(data->args[0]);
+        moveToHueCommand.direction       = static_cast<EmberAfHueDirection>(data->args[1]);
+        moveToHueCommand.transitionTime  = static_cast<uint16_t>(data->args[2]);
+        moveToHueCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        moveToHueCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         moveToHueCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveHue::Id:
+        moveHueCommand.moveMode        = static_cast<EmberAfHueMoveMode>(data->args[0]);
+        moveHueCommand.rate            = static_cast<uint8_t>(data->args[1]);
+        moveHueCommand.optionsMask     = static_cast<uint8_t>(data->args[2]);
+        moveHueCommand.optionsOverride = static_cast<uint8_t>(data->args[3]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         moveHueCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::StepHue::Id:
+        stepHueCommand.stepMode        = static_cast<EmberAfHueStepMode>(data->args[0]);
+        stepHueCommand.stepSize        = static_cast<uint8_t>(data->args[1]);
+        stepHueCommand.transitionTime  = static_cast<uint8_t>(data->args[2]);
+        stepHueCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        stepHueCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         stepHueCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveToSaturation::Id:
+        moveToSaturationCommand.saturation      = static_cast<uint8_t>(data->args[0]);
+        moveToSaturationCommand.transitionTime  = static_cast<uint16_t>(data->args[1]);
+        moveToSaturationCommand.optionsMask     = static_cast<uint8_t>(data->args[2]);
+        moveToSaturationCommand.optionsOverride = static_cast<uint8_t>(data->args[3]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         moveToSaturationCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveSaturation::Id:
+        moveSaturationCommand.moveMode        = static_cast<EmberAfSaturationMoveMode>(data->args[0]);
+        moveSaturationCommand.rate            = static_cast<uint8_t>(data->args[1]);
+        moveSaturationCommand.optionsMask     = static_cast<uint8_t>(data->args[2]);
+        moveSaturationCommand.optionsOverride = static_cast<uint8_t>(data->args[3]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         moveSaturationCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::StepSaturation::Id:
+        stepSaturationCommand.stepMode        = static_cast<EmberAfSaturationStepMode>(data->args[0]);
+        stepSaturationCommand.stepSize        = static_cast<uint8_t>(data->args[1]);
+        stepSaturationCommand.transitionTime  = static_cast<uint8_t>(data->args[2]);
+        stepSaturationCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        stepSaturationCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         stepSaturationCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveToHueAndSaturation::Id:
+        moveToHueAndSaturationCommand.hue             = static_cast<uint8_t>(data->args[0]);
+        moveToHueAndSaturationCommand.saturation      = static_cast<uint8_t>(data->args[1]);
+        moveToHueAndSaturationCommand.transitionTime  = static_cast<uint16_t>(data->args[2]);
+        moveToHueAndSaturationCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        moveToHueAndSaturationCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         moveToHueAndSaturationCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveToColor::Id:
+        moveToColorCommand.colorX          = static_cast<uint16_t>(data->args[0]);
+        moveToColorCommand.colorY          = static_cast<uint16_t>(data->args[1]);
+        moveToColorCommand.transitionTime  = static_cast<uint16_t>(data->args[2]);
+        moveToColorCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        moveToColorCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         moveToColorCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveColor::Id:
+        moveColorCommand.rateX           = static_cast<uint16_t>(data->args[0]);
+        moveColorCommand.rateY           = static_cast<uint16_t>(data->args[1]);
+        moveColorCommand.optionsMask     = static_cast<uint8_t>(data->args[2]);
+        moveColorCommand.optionsOverride = static_cast<uint8_t>(data->args[3]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         moveColorCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::StepColor::Id:
+        stepColorCommand.stepX           = static_cast<uint16_t>(data->args[0]);
+        stepColorCommand.stepY           = static_cast<uint16_t>(data->args[1]);
+        stepColorCommand.transitionTime  = static_cast<uint16_t>(data->args[2]);
+        stepColorCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        stepColorCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         stepColorCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveToColorTemperature::Id:
+        moveToColorTemperatureCommand.colorTemperature = static_cast<uint16_t>(data->args[0]);
+        moveToColorTemperatureCommand.transitionTime   = static_cast<uint16_t>(data->args[1]);
+        moveToColorTemperatureCommand.optionsMask      = static_cast<uint8_t>(data->args[2]);
+        moveToColorTemperatureCommand.optionsOverride  = static_cast<uint8_t>(data->args[3]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         moveToColorTemperatureCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::EnhancedMoveToHue::Id:
+        enhancedMoveToHueCommand.enhancedHue     = static_cast<uint16_t>(data->args[0]);
+        enhancedMoveToHueCommand.direction       = static_cast<EmberAfHueDirection>(data->args[1]);
+        enhancedMoveToHueCommand.transitionTime  = static_cast<uint16_t>(data->args[2]);
+        enhancedMoveToHueCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        enhancedMoveToHueCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         enhancedMoveToHueCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::EnhancedMoveHue::Id:
+        enhancedMoveHueCommand.moveMode        = static_cast<EmberAfHueMoveMode>(data->args[0]);
+        enhancedMoveHueCommand.rate            = static_cast<uint16_t>(data->args[1]);
+        enhancedMoveHueCommand.optionsMask     = static_cast<uint8_t>(data->args[2]);
+        enhancedMoveHueCommand.optionsOverride = static_cast<uint8_t>(data->args[3]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         enhancedMoveHueCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::EnhancedStepHue::Id:
+        enhancedStepHueCommand.stepMode        = static_cast<EmberAfHueStepMode>(data->args[0]);
+        enhancedStepHueCommand.stepSize        = static_cast<uint16_t>(data->args[1]);
+        enhancedStepHueCommand.transitionTime  = static_cast<uint16_t>(data->args[2]);
+        enhancedStepHueCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        enhancedStepHueCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         enhancedStepHueCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::EnhancedMoveToHueAndSaturation::Id:
+        enhancedMoveToHueAndSaturationCommand.enhancedHue     = static_cast<uint16_t>(data->args[0]);
+        enhancedMoveToHueAndSaturationCommand.saturation      = static_cast<uint8_t>(data->args[1]);
+        enhancedMoveToHueAndSaturationCommand.transitionTime  = static_cast<uint16_t>(data->args[2]);
+        enhancedMoveToHueAndSaturationCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        enhancedMoveToHueAndSaturationCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         enhancedMoveToHueAndSaturationCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::ColorLoopSet::Id:
+        colorLoopSetCommand.updateFlags =
+            static_cast<chip::BitMask<chip::app::Clusters::ColorControl::ColorLoopUpdateFlags>>(data->args[0]);
+        colorLoopSetCommand.action          = static_cast<EmberAfColorLoopAction>(data->args[1]);
+        colorLoopSetCommand.direction       = static_cast<EmberAfColorLoopDirection>(data->args[2]);
+        colorLoopSetCommand.time            = static_cast<uint16_t>(data->args[3]);
+        colorLoopSetCommand.startHue        = static_cast<uint16_t>(data->args[4]);
+        colorLoopSetCommand.optionsMask     = static_cast<uint8_t>(data->args[5]);
+        colorLoopSetCommand.optionsOverride = static_cast<uint8_t>(data->args[6]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         colorLoopSetCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::StopMoveStep::Id:
+        stopMoveStepCommand.optionsMask     = static_cast<uint8_t>(data->args[0]);
+        stopMoveStepCommand.optionsOverride = static_cast<uint8_t>(data->args[1]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         stopMoveStepCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveColorTemperature::Id:
+        moveColorTemperatureCommand.moveMode                      = static_cast<EmberAfHueMoveMode>(data->args[0]);
+        moveColorTemperatureCommand.rate                          = static_cast<uint16_t>(data->args[1]);
+        moveColorTemperatureCommand.colorTemperatureMinimumMireds = static_cast<uint16_t>(data->args[2]);
+        moveColorTemperatureCommand.colorTemperatureMaximumMireds = static_cast<uint16_t>(data->args[3]);
+        moveColorTemperatureCommand.optionsMask                   = static_cast<uint8_t>(data->args[4]);
+        moveColorTemperatureCommand.optionsOverride               = static_cast<uint8_t>(data->args[5]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         moveColorTemperatureCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::ColorControl::Commands::StepColorTemperature::Id:
+        stepColorTemperatureCommand.stepMode                      = static_cast<EmberAfHueStepMode>(data->args[0]);
+        stepColorTemperatureCommand.stepSize                      = static_cast<uint16_t>(data->args[1]);
+        stepColorTemperatureCommand.transitionTime                = static_cast<uint16_t>(data->args[2]);
+        stepColorTemperatureCommand.colorTemperatureMinimumMireds = static_cast<uint16_t>(data->args[3]);
+        stepColorTemperatureCommand.colorTemperatureMaximumMireds = static_cast<uint16_t>(data->args[4]);
+        stepColorTemperatureCommand.optionsMask                   = static_cast<uint8_t>(data->args[5]);
+        stepColorTemperatureCommand.optionsOverride               = static_cast<uint8_t>(data->args[6]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         stepColorTemperatureCommand, onSuccess, onFailure);
+        break;
+    }
+}
+
+void ProcessColorControlGroupBindingCommand(BindingCommandData * data, const EmberBindingTableEntry & binding)
+{
+    Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager();
+
+    Clusters::ColorControl::Commands::MoveToHue::Type moveToHueCommand;
+    Clusters::ColorControl::Commands::MoveHue::Type moveHueCommand;
+    Clusters::ColorControl::Commands::StepHue::Type stepHueCommand;
+    Clusters::ColorControl::Commands::MoveToSaturation::Type moveToSaturationCommand;
+    Clusters::ColorControl::Commands::MoveSaturation::Type moveSaturationCommand;
+    Clusters::ColorControl::Commands::StepSaturation::Type stepSaturationCommand;
+    Clusters::ColorControl::Commands::MoveToHueAndSaturation::Type moveToHueAndSaturationCommand;
+    Clusters::ColorControl::Commands::MoveToColor::Type moveToColorCommand;
+    Clusters::ColorControl::Commands::MoveColor::Type moveColorCommand;
+    Clusters::ColorControl::Commands::StepColor::Type stepColorCommand;
+    Clusters::ColorControl::Commands::MoveToColorTemperature::Type moveToColorTemperatureCommand;
+    Clusters::ColorControl::Commands::EnhancedMoveToHue::Type enhancedMoveToHueCommand;
+    Clusters::ColorControl::Commands::EnhancedMoveHue::Type enhancedMoveHueCommand;
+    Clusters::ColorControl::Commands::EnhancedStepHue::Type enhancedStepHueCommand;
+    Clusters::ColorControl::Commands::EnhancedMoveToHueAndSaturation::Type enhancedMoveToHueAndSaturationCommand;
+    Clusters::ColorControl::Commands::ColorLoopSet::Type colorLoopSetCommand;
+    Clusters::ColorControl::Commands::StopMoveStep::Type stopMoveStepCommand;
+    Clusters::ColorControl::Commands::MoveColorTemperature::Type moveColorTemperatureCommand;
+    Clusters::ColorControl::Commands::StepColorTemperature::Type stepColorTemperatureCommand;
+
+    switch (data->commandId)
+    {
+    case Clusters::ColorControl::Commands::MoveToHue::Id:
+        moveToHueCommand.hue             = static_cast<uint8_t>(data->args[0]);
+        moveToHueCommand.direction       = static_cast<EmberAfHueDirection>(data->args[1]);
+        moveToHueCommand.transitionTime  = static_cast<uint16_t>(data->args[2]);
+        moveToHueCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        moveToHueCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, moveToHueCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveHue::Id:
+        moveHueCommand.moveMode        = static_cast<EmberAfHueMoveMode>(data->args[0]);
+        moveHueCommand.rate            = static_cast<uint8_t>(data->args[1]);
+        moveHueCommand.optionsMask     = static_cast<uint8_t>(data->args[2]);
+        moveHueCommand.optionsOverride = static_cast<uint8_t>(data->args[3]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, moveHueCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::StepHue::Id:
+        stepHueCommand.stepMode        = static_cast<EmberAfHueStepMode>(data->args[0]);
+        stepHueCommand.stepSize        = static_cast<uint8_t>(data->args[1]);
+        stepHueCommand.transitionTime  = static_cast<uint8_t>(data->args[2]);
+        stepHueCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        stepHueCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, stepHueCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveToSaturation::Id:
+        moveToSaturationCommand.saturation      = static_cast<uint8_t>(data->args[0]);
+        moveToSaturationCommand.transitionTime  = static_cast<uint16_t>(data->args[1]);
+        moveToSaturationCommand.optionsMask     = static_cast<uint8_t>(data->args[2]);
+        moveToSaturationCommand.optionsOverride = static_cast<uint8_t>(data->args[3]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, moveToSaturationCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveSaturation::Id:
+        moveSaturationCommand.moveMode        = static_cast<EmberAfSaturationMoveMode>(data->args[0]);
+        moveSaturationCommand.rate            = static_cast<uint8_t>(data->args[1]);
+        moveSaturationCommand.optionsMask     = static_cast<uint8_t>(data->args[2]);
+        moveSaturationCommand.optionsOverride = static_cast<uint8_t>(data->args[3]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, moveSaturationCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::StepSaturation::Id:
+        stepSaturationCommand.stepMode        = static_cast<EmberAfSaturationStepMode>(data->args[0]);
+        stepSaturationCommand.stepSize        = static_cast<uint8_t>(data->args[1]);
+        stepSaturationCommand.transitionTime  = static_cast<uint8_t>(data->args[2]);
+        stepSaturationCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        stepSaturationCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, stepSaturationCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveToHueAndSaturation::Id:
+        moveToHueAndSaturationCommand.hue             = static_cast<uint8_t>(data->args[0]);
+        moveToHueAndSaturationCommand.saturation      = static_cast<uint8_t>(data->args[1]);
+        moveToHueAndSaturationCommand.transitionTime  = static_cast<uint16_t>(data->args[2]);
+        moveToHueAndSaturationCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        moveToHueAndSaturationCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, moveToHueAndSaturationCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveToColor::Id:
+        moveToColorCommand.colorX          = static_cast<uint16_t>(data->args[0]);
+        moveToColorCommand.colorY          = static_cast<uint16_t>(data->args[1]);
+        moveToColorCommand.transitionTime  = static_cast<uint16_t>(data->args[2]);
+        moveToColorCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        moveToColorCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, moveToColorCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveColor::Id:
+        moveColorCommand.rateX           = static_cast<uint16_t>(data->args[0]);
+        moveColorCommand.rateY           = static_cast<uint16_t>(data->args[1]);
+        moveColorCommand.optionsMask     = static_cast<uint8_t>(data->args[2]);
+        moveColorCommand.optionsOverride = static_cast<uint8_t>(data->args[3]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, moveColorCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::StepColor::Id:
+        stepColorCommand.stepX           = static_cast<uint16_t>(data->args[0]);
+        stepColorCommand.stepY           = static_cast<uint16_t>(data->args[1]);
+        stepColorCommand.transitionTime  = static_cast<uint16_t>(data->args[2]);
+        stepColorCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        stepColorCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, stepColorCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveToColorTemperature::Id:
+        moveToColorTemperatureCommand.colorTemperature = static_cast<uint16_t>(data->args[0]);
+        moveToColorTemperatureCommand.transitionTime   = static_cast<uint16_t>(data->args[1]);
+        moveToColorTemperatureCommand.optionsMask      = static_cast<uint8_t>(data->args[2]);
+        moveToColorTemperatureCommand.optionsOverride  = static_cast<uint8_t>(data->args[3]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, moveToColorTemperatureCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::EnhancedMoveToHue::Id:
+        enhancedMoveToHueCommand.enhancedHue     = static_cast<uint16_t>(data->args[0]);
+        enhancedMoveToHueCommand.direction       = static_cast<EmberAfHueDirection>(data->args[1]);
+        enhancedMoveToHueCommand.transitionTime  = static_cast<uint16_t>(data->args[2]);
+        enhancedMoveToHueCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        enhancedMoveToHueCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, enhancedMoveToHueCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::EnhancedMoveHue::Id:
+        enhancedMoveHueCommand.moveMode        = static_cast<EmberAfHueMoveMode>(data->args[0]);
+        enhancedMoveHueCommand.rate            = static_cast<uint16_t>(data->args[1]);
+        enhancedMoveHueCommand.optionsMask     = static_cast<uint8_t>(data->args[2]);
+        enhancedMoveHueCommand.optionsOverride = static_cast<uint8_t>(data->args[3]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, enhancedMoveHueCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::EnhancedStepHue::Id:
+        enhancedStepHueCommand.stepMode        = static_cast<EmberAfHueStepMode>(data->args[0]);
+        enhancedStepHueCommand.stepSize        = static_cast<uint16_t>(data->args[1]);
+        enhancedStepHueCommand.transitionTime  = static_cast<uint16_t>(data->args[2]);
+        enhancedStepHueCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        enhancedStepHueCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, enhancedStepHueCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::EnhancedMoveToHueAndSaturation::Id:
+        enhancedMoveToHueAndSaturationCommand.enhancedHue     = static_cast<uint16_t>(data->args[0]);
+        enhancedMoveToHueAndSaturationCommand.saturation      = static_cast<uint8_t>(data->args[1]);
+        enhancedMoveToHueAndSaturationCommand.transitionTime  = static_cast<uint16_t>(data->args[2]);
+        enhancedMoveToHueAndSaturationCommand.optionsMask     = static_cast<uint8_t>(data->args[3]);
+        enhancedMoveToHueAndSaturationCommand.optionsOverride = static_cast<uint8_t>(data->args[4]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId,
+                                              enhancedMoveToHueAndSaturationCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::ColorLoopSet::Id:
+        colorLoopSetCommand.updateFlags =
+            static_cast<chip::BitMask<chip::app::Clusters::ColorControl::ColorLoopUpdateFlags>>(data->args[0]);
+        colorLoopSetCommand.action          = static_cast<EmberAfColorLoopAction>(data->args[1]);
+        colorLoopSetCommand.direction       = static_cast<EmberAfColorLoopDirection>(data->args[2]);
+        colorLoopSetCommand.time            = static_cast<uint16_t>(data->args[3]);
+        colorLoopSetCommand.startHue        = static_cast<uint16_t>(data->args[4]);
+        colorLoopSetCommand.optionsMask     = static_cast<uint8_t>(data->args[5]);
+        colorLoopSetCommand.optionsOverride = static_cast<uint8_t>(data->args[6]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, colorLoopSetCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::StopMoveStep::Id:
+        stopMoveStepCommand.optionsMask     = static_cast<uint8_t>(data->args[0]);
+        stopMoveStepCommand.optionsOverride = static_cast<uint8_t>(data->args[1]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, stopMoveStepCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::MoveColorTemperature::Id:
+        moveColorTemperatureCommand.moveMode                      = static_cast<EmberAfHueMoveMode>(data->args[0]);
+        moveColorTemperatureCommand.rate                          = static_cast<uint16_t>(data->args[1]);
+        moveColorTemperatureCommand.colorTemperatureMinimumMireds = static_cast<uint16_t>(data->args[2]);
+        moveColorTemperatureCommand.colorTemperatureMaximumMireds = static_cast<uint16_t>(data->args[3]);
+        moveColorTemperatureCommand.optionsMask                   = static_cast<uint8_t>(data->args[4]);
+        moveColorTemperatureCommand.optionsOverride               = static_cast<uint8_t>(data->args[5]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, moveColorTemperatureCommand);
+        break;
+
+    case Clusters::ColorControl::Commands::StepColorTemperature::Id:
+        stepColorTemperatureCommand.stepMode                      = static_cast<EmberAfHueStepMode>(data->args[0]);
+        stepColorTemperatureCommand.stepSize                      = static_cast<uint16_t>(data->args[1]);
+        stepColorTemperatureCommand.transitionTime                = static_cast<uint16_t>(data->args[2]);
+        stepColorTemperatureCommand.colorTemperatureMinimumMireds = static_cast<uint16_t>(data->args[3]);
+        stepColorTemperatureCommand.colorTemperatureMaximumMireds = static_cast<uint16_t>(data->args[4]);
+        stepColorTemperatureCommand.optionsMask                   = static_cast<uint8_t>(data->args[5]);
+        stepColorTemperatureCommand.optionsOverride               = static_cast<uint8_t>(data->args[6]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, stepColorTemperatureCommand);
+        break;
+    }
+}
+
+#if CONFIG_ENABLE_CHIP_SHELL
+/********************************************************
+ * ColorControl switch shell functions
+ *********************************************************/
+
+CHIP_ERROR ColorControlHelpHandler(int argc, char ** argv)
+{
+    sShellSwitchColorControlSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc == 0)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    return sShellSwitchColorControlSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR MoveToHueCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveToHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR MoveHueCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR StepHueCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::StepHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR MoveToSaturationCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveToSaturation::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR MoveSaturationCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveSaturation::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR StepSaturationCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::StepSaturation::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR MoveToHueAndSaturationCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveToHueAndSaturation::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR MoveToColorCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveToColor::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR MoveColorCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveColor::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR StepColorCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::StepColor::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR MoveToColorTemperatureCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveToColorTemperature::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR EnhancedMoveToHueCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::EnhancedMoveToHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR EnhancedMoveHueCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::EnhancedMoveHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR EnhancedStepHueCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::EnhancedStepHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR EnhancedMoveToHueAndSaturationCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::EnhancedMoveToHueAndSaturation::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorLoopSetCommandHandler(int argc, char ** argv)
+{
+    if (argc != 7)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::ColorLoopSet::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->args[5]             = atoi(argv[5]);
+    data->args[6]             = atoi(argv[6]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR StopMoveStepCommandHandler(int argc, char ** argv)
+{
+    if (argc != 2)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::StopMoveStep::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR MoveColorTemperatureCommandHandler(int argc, char ** argv)
+{
+    if (argc != 6)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveColorTemperature::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->args[5]             = atoi(argv[5]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR StepColorTemperatureCommandHandler(int argc, char ** argv)
+{
+    if (argc != 7)
+    {
+        return ColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::StepColorTemperature::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->args[5]             = atoi(argv[5]);
+    data->args[6]             = atoi(argv[6]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+/********************************************************
+ * ColorControl Read switch shell functions
+ *********************************************************/
+
+CHIP_ERROR ColorControlReadHelpHandler(int argc, char ** argv)
+{
+    sShellSwitchColorControlReadSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlRead(int argc, char ** argv)
+{
+    if (argc == 0)
+    {
+        return ColorControlReadHelpHandler(argc, argv);
+    }
+
+    return sShellSwitchColorControlReadSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR ColorControlReadAttributeList(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::AttributeList::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadCurrentHue(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::CurrentHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadCurrentSaturation(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::CurrentSaturation::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadRemainingTime(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::RemainingTime::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadCurrentX(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::CurrentX::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadCurrentY(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::CurrentY::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadDriftCompensation(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::DriftCompensation::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadCompensationText(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::CompensationText::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorTemperature(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorTemperatureMireds::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorMode(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorMode::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadOptions(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Options::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadNumberOfPrimaries(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::NumberOfPrimaries::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary1X(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary1X::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary1Y(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary1Y::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary1Intensity(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary1Intensity::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary2X(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary2X::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary2Y(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary2Y::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary2Intensity(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary2Intensity::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary3X(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary3X::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary3Y(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary3Y::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary3Intensity(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary3Intensity::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary4X(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary4X::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary4Y(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary4Y::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary4Intensity(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary4Intensity::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary5X(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary5X::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary5Y(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary5Y::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary5Intensity(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary5Intensity::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary6X(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary6X::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary6Y(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary6Y::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadPrimary6Intensity(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::Primary6Intensity::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadWhitePointX(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::WhitePointX::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadWhitePointY(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::WhitePointY::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorPointRX(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorPointRX::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorPointRY(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorPointRY::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorPointRIntensity(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorPointRIntensity::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorPointGX(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorPointGX::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorPointGY(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorPointGY::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorPointGIntensity(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorPointGIntensity::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorPointBX(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorPointBX::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorPointBY(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorPointBY::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorPointBIntensity(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorPointBIntensity::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadEnhancedCurrentHue(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::EnhancedCurrentHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadEnhancedColorMode(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::EnhancedColorMode::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorLoopActive(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorLoopActive::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorLoopDirection(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorLoopDirection::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorLoopTime(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorLoopTime::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorLoopStartEnhancedHue(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorLoopStartEnhancedHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorLoopStoredEnhancedHue(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorLoopStoredEnhancedHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorCapabilities(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorCapabilities::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorTempPhysicalMinMireds(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorTempPhysicalMinMireds::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadColorTempPhysicalMaxMireds(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::ColorTempPhysicalMaxMireds::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadCoupleColorTempToLevelMinMireds(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::CoupleColorTempToLevelMinMireds::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ColorControlReadStartUpColorTemperatureMireds(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::ColorControl::Attributes::StartUpColorTemperatureMireds::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+/********************************************************
+ * Groups ColorControl switch shell functions
+ *********************************************************/
+
+CHIP_ERROR GroupsColorControlHelpHandler(int argc, char ** argv)
+{
+    sShellSwitchGroupsColorControlSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsColorControlSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc == 0)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    return sShellSwitchGroupsColorControlSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR GroupsMoveToHueCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveToHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsMoveHueCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsStepHueCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::StepHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsMoveToSaturationCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveToSaturation::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsMoveSaturationCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveSaturation::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsStepSaturationCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::StepSaturation::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsMoveToHueAndSaturationCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveToHueAndSaturation::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsMoveToColorCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveToColor::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsMoveColorCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveColor::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsStepColorCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveColor::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsMoveToColorTemperatureCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveColor::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsEnhancedMoveToHueCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::EnhancedMoveToHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsEnhancedMoveHueCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::EnhancedMoveHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsEnhancedStepHueCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::EnhancedStepHue::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsEnhancedMoveToHueAndSaturationCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::EnhancedMoveToHueAndSaturation::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsColorLoopSetCommandHandler(int argc, char ** argv)
+{
+    if (argc != 7)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::ColorLoopSet::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->args[5]             = atoi(argv[5]);
+    data->args[6]             = atoi(argv[6]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsStopMoveStepCommandHandler(int argc, char ** argv)
+{
+    if (argc != 2)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::StopMoveStep::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsMoveColorTemperatureCommandHandler(int argc, char ** argv)
+{
+    if (argc != 6)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::MoveColorTemperature::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->args[5]             = atoi(argv[5]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsStepColorTemperatureCommandHandler(int argc, char ** argv)
+{
+    if (argc != 7)
+    {
+        return GroupsColorControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::ColorControl::Commands::StepColorTemperature::Id;
+    data->clusterId           = Clusters::ColorControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->args[5]             = atoi(argv[5]);
+    data->args[6]             = atoi(argv[6]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+#endif // CONFIG_ENABLE_CHIP_SHELL
diff --git a/examples/all-clusters-app/ameba/main/include/IdentifyCommand.h b/examples/all-clusters-app/ameba/main/include/IdentifyCommand.h
new file mode 100644
index 0000000..ab93460
--- /dev/null
+++ b/examples/all-clusters-app/ameba/main/include/IdentifyCommand.h
@@ -0,0 +1,270 @@
+/*
+ *
+ *    Copyright (c) 2022 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include "controller/InvokeInteraction.h"
+#include "controller/ReadInteraction.h"
+#include <app/clusters/bindings/bindings.h>
+
+#if CONFIG_ENABLE_CHIP_SHELL
+#include "lib/shell/Engine.h"
+#include "lib/shell/commands/Help.h"
+#endif // ENABLE_CHIP_SHELL
+
+using namespace chip;
+using namespace chip::app;
+
+#if CONFIG_ENABLE_CHIP_SHELL
+using Shell::Engine;
+using Shell::shell_command_t;
+using Shell::streamer_get;
+using Shell::streamer_printf;
+
+Engine sShellSwitchIdentifySubCommands;
+Engine sShellSwitchIdentifyReadSubCommands;
+Engine sShellSwitchGroupsIdentifySubCommands;
+#endif // defined(ENABLE_CHIP_SHELL)
+
+void ProcessIdentifyUnicastBindingRead(BindingCommandData * data, const EmberBindingTableEntry & binding,
+                                       OperationalDeviceProxy * peer_device)
+{
+    auto onSuccess = [](const ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
+        ChipLogProgress(NotSpecified, "Read Identify attribute succeeds");
+    };
+
+    auto onFailure = [](const ConcreteDataAttributePath * attributePath, CHIP_ERROR error) {
+        ChipLogError(NotSpecified, "Read Identify attribute failed: %" CHIP_ERROR_FORMAT, error.Format());
+    };
+
+    VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady());
+
+    switch (data->attributeId)
+    {
+    case Clusters::Identify::Attributes::AttributeList::Id:
+        Controller::ReadAttribute<Clusters::Identify::Attributes::AttributeList::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Identify::Attributes::IdentifyTime::Id:
+        Controller::ReadAttribute<Clusters::Identify::Attributes::IdentifyTime::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Identify::Attributes::IdentifyType::Id:
+        Controller::ReadAttribute<Clusters::Identify::Attributes::IdentifyType::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+    }
+}
+
+void ProcessIdentifyUnicastBindingCommand(BindingCommandData * data, const EmberBindingTableEntry & binding,
+                                          OperationalDeviceProxy * peer_device)
+{
+    auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) {
+        ChipLogProgress(NotSpecified, "Identify command succeeds");
+    };
+
+    auto onFailure = [](CHIP_ERROR error) {
+        ChipLogError(NotSpecified, "Identify command failed: %" CHIP_ERROR_FORMAT, error.Format());
+    };
+
+    VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady());
+
+    Clusters::Identify::Commands::Identify::Type identifyCommand;
+    Clusters::Identify::Commands::TriggerEffect::Type triggerEffectCommand;
+
+    switch (data->commandId)
+    {
+    case Clusters::Identify::Commands::Identify::Id:
+        identifyCommand.identifyTime = static_cast<uint16_t>(data->args[0]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         identifyCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::Identify::Commands::TriggerEffect::Id:
+        triggerEffectCommand.effectIdentifier = static_cast<EmberAfIdentifyEffectIdentifier>(data->args[0]);
+        triggerEffectCommand.effectVariant    = static_cast<EmberAfIdentifyEffectVariant>(data->args[1]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         triggerEffectCommand, onSuccess, onFailure);
+        break;
+    }
+}
+
+void ProcessIdentifyGroupBindingCommand(BindingCommandData * data, const EmberBindingTableEntry & binding)
+{
+    Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager();
+
+    Clusters::Identify::Commands::Identify::Type identifyCommand;
+    Clusters::Identify::Commands::TriggerEffect::Type triggerEffectCommand;
+
+    switch (data->commandId)
+    {
+    case Clusters::Identify::Commands::Identify::Id:
+        identifyCommand.identifyTime = static_cast<uint16_t>(data->args[0]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, identifyCommand);
+        break;
+
+    case Clusters::Identify::Commands::TriggerEffect::Id:
+        triggerEffectCommand.effectIdentifier = static_cast<EmberAfIdentifyEffectIdentifier>(data->args[0]);
+        triggerEffectCommand.effectVariant    = static_cast<EmberAfIdentifyEffectVariant>(data->args[1]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, triggerEffectCommand);
+        break;
+    }
+}
+
+#if CONFIG_ENABLE_CHIP_SHELL
+/********************************************************
+ * Identify switch shell functions
+ *********************************************************/
+
+CHIP_ERROR IdentifyHelpHandler(int argc, char ** argv)
+{
+    sShellSwitchIdentifySubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR IdentifySwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc == 0)
+    {
+        return IdentifyHelpHandler(argc, argv);
+    }
+
+    return sShellSwitchIdentifySubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR IdentifyCommandHandler(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::Identify::Commands::Identify::Id;
+    data->clusterId           = Clusters::Identify::Id;
+    data->args[0]             = atoi(argv[0]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR TriggerEffectSwitchCommandHandler(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::Identify::Commands::TriggerEffect::Id;
+    data->clusterId           = Clusters::Identify::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+/********************************************************
+ * Identify Read switch shell functions
+ *********************************************************/
+
+CHIP_ERROR IdentifyReadHelpHandler(int argc, char ** argv)
+{
+    sShellSwitchIdentifyReadSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR IdentifyRead(int argc, char ** argv)
+{
+    if (argc == 0)
+    {
+        return IdentifyReadHelpHandler(argc, argv);
+    }
+
+    return sShellSwitchIdentifyReadSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR IdentifyReadAttributeList(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Identify::Attributes::AttributeList::Id;
+    data->clusterId           = Clusters::Identify::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR IdentifyReadIdentifyTime(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Identify::Attributes::IdentifyTime::Id;
+    data->clusterId           = Clusters::Identify::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR IdentifyReadIdentifyType(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Identify::Attributes::IdentifyType::Id;
+    data->clusterId           = Clusters::Identify::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+/********************************************************
+ * Groups Identify switch shell functions
+ *********************************************************/
+
+CHIP_ERROR GroupsIdentifyHelpHandler(int argc, char ** argv)
+{
+    sShellSwitchGroupsIdentifySubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsIdentifySwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc == 0)
+    {
+        return GroupsIdentifyHelpHandler(argc, argv);
+    }
+
+    return sShellSwitchGroupsIdentifySubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR GroupIdentifyCommandHandler(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::Identify::Commands::Identify::Id;
+    data->clusterId           = Clusters::Identify::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupTriggerEffectSwitchCommandHandler(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::Identify::Commands::TriggerEffect::Id;
+    data->clusterId           = Clusters::Identify::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+#endif // CONFIG_ENABLE_CHIP_SHELL
diff --git a/examples/all-clusters-app/ameba/main/include/LevelControlCommands.h b/examples/all-clusters-app/ameba/main/include/LevelControlCommands.h
new file mode 100644
index 0000000..a84dcb8
--- /dev/null
+++ b/examples/all-clusters-app/ameba/main/include/LevelControlCommands.h
@@ -0,0 +1,843 @@
+/*
+ *
+ *    Copyright (c) 2022 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include "controller/InvokeInteraction.h"
+#include "controller/ReadInteraction.h"
+#include <app/clusters/bindings/bindings.h>
+
+#if CONFIG_ENABLE_CHIP_SHELL
+#include "lib/shell/Engine.h"
+#include "lib/shell/commands/Help.h"
+#endif // ENABLE_CHIP_SHELL
+
+using namespace chip;
+using namespace chip::app;
+
+#if CONFIG_ENABLE_CHIP_SHELL
+using chip::app::Clusters::LevelControl::LevelControlOptions;
+using Shell::Engine;
+using Shell::shell_command_t;
+using Shell::streamer_get;
+using Shell::streamer_printf;
+
+Engine sShellSwitchLevelControlSubCommands;
+Engine sShellSwitchLevelControlReadSubCommands;
+Engine sShellSwitchGroupsLevelControlSubCommands;
+#endif // defined(ENABLE_CHIP_SHELL)
+
+void ProcessLevelControlUnicastBindingRead(BindingCommandData * data, const EmberBindingTableEntry & binding,
+                                           OperationalDeviceProxy * peer_device)
+{
+    auto onSuccess = [](const ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
+        ChipLogProgress(NotSpecified, "Read LevelControl attribute succeeds");
+    };
+
+    auto onFailure = [](const ConcreteDataAttributePath * attributePath, CHIP_ERROR error) {
+        ChipLogError(NotSpecified, "Read LevelControl attribute failed: %" CHIP_ERROR_FORMAT, error.Format());
+    };
+
+    VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady());
+
+    switch (data->attributeId)
+    {
+    case Clusters::LevelControl::Attributes::AttributeList::Id:
+        Controller::ReadAttribute<Clusters::LevelControl::Attributes::AttributeList::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Attributes::CurrentLevel::Id:
+        Controller::ReadAttribute<Clusters::LevelControl::Attributes::CurrentLevel::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Attributes::RemainingTime::Id:
+        Controller::ReadAttribute<Clusters::LevelControl::Attributes::RemainingTime::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Attributes::MinLevel::Id:
+        Controller::ReadAttribute<Clusters::LevelControl::Attributes::MinLevel::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Attributes::MaxLevel::Id:
+        Controller::ReadAttribute<Clusters::LevelControl::Attributes::MaxLevel::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Attributes::CurrentFrequency::Id:
+        Controller::ReadAttribute<Clusters::LevelControl::Attributes::CurrentFrequency::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Attributes::MinFrequency::Id:
+        Controller::ReadAttribute<Clusters::LevelControl::Attributes::MinFrequency::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Attributes::MaxFrequency::Id:
+        Controller::ReadAttribute<Clusters::LevelControl::Attributes::MaxFrequency::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Attributes::Options::Id:
+        Controller::ReadAttribute<Clusters::LevelControl::Attributes::Options::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Attributes::OnOffTransitionTime::Id:
+        Controller::ReadAttribute<Clusters::LevelControl::Attributes::OnOffTransitionTime::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Attributes::OnLevel::Id:
+        Controller::ReadAttribute<Clusters::LevelControl::Attributes::OnLevel::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Attributes::OnTransitionTime::Id:
+        Controller::ReadAttribute<Clusters::LevelControl::Attributes::OnTransitionTime::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Attributes::OffTransitionTime::Id:
+        Controller::ReadAttribute<Clusters::LevelControl::Attributes::OffTransitionTime::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Attributes::DefaultMoveRate::Id:
+        Controller::ReadAttribute<Clusters::LevelControl::Attributes::DefaultMoveRate::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Attributes::StartUpCurrentLevel::Id:
+        Controller::ReadAttribute<Clusters::LevelControl::Attributes::StartUpCurrentLevel::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+    }
+}
+
+void ProcessLevelControlUnicastBindingCommand(BindingCommandData * data, const EmberBindingTableEntry & binding,
+                                              OperationalDeviceProxy * peer_device)
+{
+    auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) {
+        ChipLogProgress(NotSpecified, "LevelControl command succeeds");
+    };
+
+    auto onFailure = [](CHIP_ERROR error) {
+        ChipLogError(NotSpecified, "LevelControl command failed: %" CHIP_ERROR_FORMAT, error.Format());
+    };
+
+    VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady());
+
+    Clusters::LevelControl::Commands::MoveToLevel::Type moveToLevelCommand;
+    Clusters::LevelControl::Commands::Move::Type moveCommand;
+    Clusters::LevelControl::Commands::Step::Type stepCommand;
+    Clusters::LevelControl::Commands::Stop::Type stopCommand;
+    Clusters::LevelControl::Commands::MoveToLevelWithOnOff::Type moveToLevelWithOnOffCommand;
+    Clusters::LevelControl::Commands::MoveWithOnOff::Type moveWithOnOffCommand;
+    Clusters::LevelControl::Commands::StepWithOnOff::Type stepWithOnOffCommand;
+    Clusters::LevelControl::Commands::StopWithOnOff::Type stopWithOnOffCommand;
+
+    switch (data->commandId)
+    {
+    case Clusters::LevelControl::Commands::MoveToLevel::Id:
+        moveToLevelCommand.level           = static_cast<uint8_t>(data->args[0]);
+        moveToLevelCommand.transitionTime  = static_cast<DataModel::Nullable<uint16_t>>(data->args[1]);
+        moveToLevelCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[2]);
+        moveToLevelCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[3]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         moveToLevelCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Commands::Move::Id:
+        moveCommand.moveMode        = static_cast<EmberAfMoveMode>(data->args[0]);
+        moveCommand.rate            = static_cast<DataModel::Nullable<uint8_t>>(data->args[1]);
+        moveCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[2]);
+        moveCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[3]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         moveCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Commands::Step::Id:
+        stepCommand.stepMode        = static_cast<EmberAfStepMode>(data->args[0]);
+        stepCommand.stepSize        = static_cast<uint8_t>(data->args[1]);
+        stepCommand.transitionTime  = static_cast<DataModel::Nullable<uint16_t>>(data->args[2]);
+        stepCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[3]);
+        stepCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[4]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         stepCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Commands::Stop::Id:
+        stopCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[0]);
+        stopCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[1]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         stopCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Commands::MoveToLevelWithOnOff::Id:
+        moveToLevelWithOnOffCommand.level           = static_cast<uint8_t>(data->args[0]);
+        moveToLevelWithOnOffCommand.transitionTime  = static_cast<DataModel::Nullable<uint16_t>>(data->args[1]);
+        moveToLevelWithOnOffCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[2]);
+        moveToLevelWithOnOffCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[3]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         moveToLevelWithOnOffCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Commands::MoveWithOnOff::Id:
+        moveWithOnOffCommand.moveMode        = static_cast<EmberAfMoveMode>(data->args[0]);
+        moveWithOnOffCommand.rate            = static_cast<DataModel::Nullable<uint8_t>>(data->args[1]);
+        moveWithOnOffCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[2]);
+        moveWithOnOffCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[3]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         moveWithOnOffCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Commands::StepWithOnOff::Id:
+        stepWithOnOffCommand.stepMode        = static_cast<EmberAfStepMode>(data->args[0]);
+        stepWithOnOffCommand.stepSize        = static_cast<uint8_t>(data->args[1]);
+        stepWithOnOffCommand.transitionTime  = static_cast<DataModel::Nullable<uint16_t>>(data->args[2]);
+        stepWithOnOffCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[3]);
+        stepWithOnOffCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[4]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         stepWithOnOffCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::LevelControl::Commands::StopWithOnOff::Id:
+        stopWithOnOffCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[0]);
+        stopWithOnOffCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[1]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         stopWithOnOffCommand, onSuccess, onFailure);
+        break;
+    }
+}
+
+void ProcessLevelControlGroupBindingCommand(BindingCommandData * data, const EmberBindingTableEntry & binding)
+{
+    Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager();
+
+    Clusters::LevelControl::Commands::MoveToLevel::Type moveToLevelCommand;
+    Clusters::LevelControl::Commands::Move::Type moveCommand;
+    Clusters::LevelControl::Commands::Step::Type stepCommand;
+    Clusters::LevelControl::Commands::Stop::Type stopCommand;
+    Clusters::LevelControl::Commands::MoveToLevelWithOnOff::Type moveToLevelWithOnOffCommand;
+    Clusters::LevelControl::Commands::MoveWithOnOff::Type moveWithOnOffCommand;
+    Clusters::LevelControl::Commands::StepWithOnOff::Type stepWithOnOffCommand;
+    Clusters::LevelControl::Commands::StopWithOnOff::Type stopWithOnOffCommand;
+
+    switch (data->commandId)
+    {
+    case Clusters::LevelControl::Commands::MoveToLevel::Id:
+        moveToLevelCommand.level           = static_cast<uint8_t>(data->args[0]);
+        moveToLevelCommand.transitionTime  = static_cast<DataModel::Nullable<uint16_t>>(data->args[1]);
+        moveToLevelCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[2]);
+        moveToLevelCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[3]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, moveToLevelCommand);
+        break;
+
+    case Clusters::LevelControl::Commands::Move::Id:
+        moveCommand.moveMode        = static_cast<EmberAfMoveMode>(data->args[0]);
+        moveCommand.rate            = static_cast<DataModel::Nullable<uint8_t>>(data->args[1]);
+        moveCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[2]);
+        moveCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[3]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, moveCommand);
+        break;
+
+    case Clusters::LevelControl::Commands::Step::Id:
+        stepCommand.stepMode        = static_cast<EmberAfStepMode>(data->args[0]);
+        stepCommand.stepSize        = static_cast<uint8_t>(data->args[1]);
+        stepCommand.transitionTime  = static_cast<DataModel::Nullable<uint16_t>>(data->args[2]);
+        stepCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[3]);
+        stepCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[4]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, stepCommand);
+        break;
+
+    case Clusters::LevelControl::Commands::Stop::Id:
+        stopCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[0]);
+        stopCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[1]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, stopCommand);
+        break;
+
+    case Clusters::LevelControl::Commands::MoveToLevelWithOnOff::Id:
+        moveToLevelWithOnOffCommand.level           = static_cast<uint8_t>(data->args[0]);
+        moveToLevelWithOnOffCommand.transitionTime  = static_cast<DataModel::Nullable<uint16_t>>(data->args[1]);
+        moveToLevelWithOnOffCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[2]);
+        moveToLevelWithOnOffCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[3]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, moveToLevelWithOnOffCommand);
+        break;
+
+    case Clusters::LevelControl::Commands::MoveWithOnOff::Id:
+        moveWithOnOffCommand.moveMode        = static_cast<EmberAfMoveMode>(data->args[0]);
+        moveWithOnOffCommand.rate            = static_cast<DataModel::Nullable<uint8_t>>(data->args[1]);
+        moveWithOnOffCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[2]);
+        moveWithOnOffCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[3]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, moveWithOnOffCommand);
+        break;
+
+    case Clusters::LevelControl::Commands::StepWithOnOff::Id:
+        stepWithOnOffCommand.stepMode        = static_cast<EmberAfStepMode>(data->args[0]);
+        stepWithOnOffCommand.stepSize        = static_cast<uint8_t>(data->args[1]);
+        stepWithOnOffCommand.transitionTime  = static_cast<DataModel::Nullable<uint16_t>>(data->args[2]);
+        stepWithOnOffCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[3]);
+        stepWithOnOffCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[4]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, stepWithOnOffCommand);
+        break;
+
+    case Clusters::LevelControl::Commands::StopWithOnOff::Id:
+        stopWithOnOffCommand.optionsMask     = static_cast<chip::BitMask<LevelControlOptions>>(data->args[0]);
+        stopWithOnOffCommand.optionsOverride = static_cast<chip::BitMask<LevelControlOptions>>(data->args[1]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, stopWithOnOffCommand);
+        break;
+    }
+}
+
+#if CONFIG_ENABLE_CHIP_SHELL
+/********************************************************
+ * LevelControl switch shell functions
+ *********************************************************/
+
+CHIP_ERROR LevelControlHelpHandler(int argc, char ** argv)
+{
+    sShellSwitchLevelControlSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc == 0)
+    {
+        return LevelControlHelpHandler(argc, argv);
+    }
+
+    return sShellSwitchLevelControlSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR MoveToLevelSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return LevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::MoveToLevel::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR MoveSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return LevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::Move::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR StepSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return LevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::Step::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR StopSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 2)
+    {
+        return LevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::Stop::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR MoveToLevelWithOnOffSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return LevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::MoveToLevelWithOnOff::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR MoveWithOnOffSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return LevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::MoveWithOnOff::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR StepWithOnOffSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return LevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::StepWithOnOff::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR StopWithOnOffSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 2)
+    {
+        return LevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::StopWithOnOff::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+/********************************************************
+ * LevelControl Read switch shell functions
+ *********************************************************/
+
+CHIP_ERROR LevelControlReadHelpHandler(int argc, char ** argv)
+{
+    sShellSwitchLevelControlReadSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlRead(int argc, char ** argv)
+{
+    if (argc == 0)
+    {
+        return LevelControlReadHelpHandler(argc, argv);
+    }
+
+    return sShellSwitchLevelControlReadSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR LevelControlReadAttributeList(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::LevelControl::Attributes::AttributeList::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlReadCurrentLevel(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::LevelControl::Attributes::CurrentLevel::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->isReadAttribute     = true;
+    ChipLogProgress(NotSpecified, "Read cluster=0x%x, attribute=0x%08x", data->clusterId, data->attributeId);
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlReadRemainingTime(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::LevelControl::Attributes::RemainingTime::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->isReadAttribute     = true;
+    ChipLogProgress(NotSpecified, "Read cluster=0x%x, attribute=0x%08x", data->clusterId, data->attributeId);
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlReadMinLevel(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::LevelControl::Attributes::MinLevel::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->isReadAttribute     = true;
+    ChipLogProgress(NotSpecified, "Read cluster=0x%x, attribute=0x%08x", data->clusterId, data->attributeId);
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlReadMaxLevel(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::LevelControl::Attributes::MaxLevel::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->isReadAttribute     = true;
+    ChipLogProgress(NotSpecified, "Read cluster=0x%x, attribute=0x%08x", data->clusterId, data->attributeId);
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlReadCurrentFrequency(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::LevelControl::Attributes::CurrentFrequency::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->isReadAttribute     = true;
+    ChipLogProgress(NotSpecified, "Read cluster=0x%x, attribute=0x%08x", data->clusterId, data->attributeId);
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlReadMinFrequency(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::LevelControl::Attributes::MinFrequency::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->isReadAttribute     = true;
+    ChipLogProgress(NotSpecified, "Read cluster=0x%x, attribute=0x%08x", data->clusterId, data->attributeId);
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlReadMaxFrequency(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::LevelControl::Attributes::MaxFrequency::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->isReadAttribute     = true;
+    ChipLogProgress(NotSpecified, "Read cluster=0x%x, attribute=0x%08x", data->clusterId, data->attributeId);
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlReadOptions(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::LevelControl::Attributes::Options::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->isReadAttribute     = true;
+    ChipLogProgress(NotSpecified, "Read cluster=0x%x, attribute=0x%08x", data->clusterId, data->attributeId);
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlReadOnOffTransitionTime(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::LevelControl::Attributes::OnOffTransitionTime::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->isReadAttribute     = true;
+    ChipLogProgress(NotSpecified, "Read cluster=0x%x, attribute=0x%08x", data->clusterId, data->attributeId);
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlReadOnLevel(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::LevelControl::Attributes::OnLevel::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->isReadAttribute     = true;
+    ChipLogProgress(NotSpecified, "Read cluster=0x%x, attribute=0x%08x", data->clusterId, data->attributeId);
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlReadOnTransitionTime(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::LevelControl::Attributes::OnTransitionTime::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->isReadAttribute     = true;
+    ChipLogProgress(NotSpecified, "Read cluster=0x%x, attribute=0x%08x", data->clusterId, data->attributeId);
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlReadOffTransitionTime(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::LevelControl::Attributes::OffTransitionTime::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->isReadAttribute     = true;
+    ChipLogProgress(NotSpecified, "Read cluster=0x%x, attribute=0x%08x", data->clusterId, data->attributeId);
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlReadDefaultMoveRate(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::LevelControl::Attributes::DefaultMoveRate::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->isReadAttribute     = true;
+    ChipLogProgress(NotSpecified, "Read cluster=0x%x, attribute=0x%08x", data->clusterId, data->attributeId);
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR LevelControlReadStartUpCurrentLevel(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::LevelControl::Attributes::StartUpCurrentLevel::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->isReadAttribute     = true;
+    ChipLogProgress(NotSpecified, "Read cluster=0x%x, attribute=0x%08x", data->clusterId, data->attributeId);
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+/********************************************************
+ * Groups LevelControl switch shell functions
+ *********************************************************/
+
+CHIP_ERROR GroupsLevelControlHelpHandler(int argc, char ** argv)
+{
+    sShellSwitchGroupsLevelControlSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsLevelControlSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc == 0)
+    {
+        return GroupsLevelControlHelpHandler(argc, argv);
+    }
+
+    return sShellSwitchGroupsLevelControlSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR GroupsMoveToLevelSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return GroupsLevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::MoveToLevel::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsMoveSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return GroupsLevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::Move::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsStepSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return GroupsLevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::Step::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsStopSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 2)
+    {
+        return GroupsLevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::Stop::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsMoveToLevelWithOnOffSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return GroupsLevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::MoveToLevelWithOnOff::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsMoveWithOnOffSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 4)
+    {
+        return GroupsLevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::MoveWithOnOff::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsStepWithOnOffSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 5)
+    {
+        return GroupsLevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::StepWithOnOff::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->args[3]             = atoi(argv[3]);
+    data->args[4]             = atoi(argv[4]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsStopWithOnOffSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 2)
+    {
+        return GroupsLevelControlHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::LevelControl::Commands::StopWithOnOff::Id;
+    data->clusterId           = Clusters::LevelControl::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+#endif // CONFIG_ENABLE_CHIP_SHELL
diff --git a/examples/all-clusters-app/ameba/main/include/OnOffCommands.h b/examples/all-clusters-app/ameba/main/include/OnOffCommands.h
new file mode 100644
index 0000000..47dfe56
--- /dev/null
+++ b/examples/all-clusters-app/ameba/main/include/OnOffCommands.h
@@ -0,0 +1,474 @@
+/*
+ *
+ *    Copyright (c) 2022 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include "controller/InvokeInteraction.h"
+#include "controller/ReadInteraction.h"
+#include <app/clusters/bindings/bindings.h>
+
+#if CONFIG_ENABLE_CHIP_SHELL
+#include "lib/shell/Engine.h"
+#include "lib/shell/commands/Help.h"
+#endif // ENABLE_CHIP_SHELL
+
+using namespace chip;
+using namespace chip::app;
+
+#if CONFIG_ENABLE_CHIP_SHELL
+using Shell::Engine;
+using Shell::shell_command_t;
+using Shell::streamer_get;
+using Shell::streamer_printf;
+
+Engine sShellSwitchOnOffSubCommands;
+Engine sShellSwitchOnOffReadSubCommands;
+Engine sShellSwitchGroupsOnOffSubCommands;
+#endif // defined(ENABLE_CHIP_SHELL)
+
+void ProcessOnOffUnicastBindingRead(BindingCommandData * data, const EmberBindingTableEntry & binding,
+                                    OperationalDeviceProxy * peer_device)
+{
+    auto onSuccess = [](const ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
+        ChipLogProgress(NotSpecified, "Read OnOff attribute succeeds");
+    };
+
+    auto onFailure = [](const ConcreteDataAttributePath * attributePath, CHIP_ERROR error) {
+        ChipLogError(NotSpecified, "Read OnOff attribute failed: %" CHIP_ERROR_FORMAT, error.Format());
+    };
+
+    VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady());
+
+    switch (data->attributeId)
+    {
+    case Clusters::OnOff::Attributes::AttributeList::Id:
+        Controller::ReadAttribute<Clusters::OnOff::Attributes::AttributeList::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::OnOff::Attributes::OnOff::Id:
+        Controller::ReadAttribute<Clusters::OnOff::Attributes::OnOff::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::OnOff::Attributes::GlobalSceneControl::Id:
+        Controller::ReadAttribute<Clusters::OnOff::Attributes::GlobalSceneControl::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::OnOff::Attributes::OnTime::Id:
+        Controller::ReadAttribute<Clusters::OnOff::Attributes::OnTime::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::OnOff::Attributes::OffWaitTime::Id:
+        Controller::ReadAttribute<Clusters::OnOff::Attributes::OffWaitTime::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::OnOff::Attributes::StartUpOnOff::Id:
+        Controller::ReadAttribute<Clusters::OnOff::Attributes::StartUpOnOff::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+    }
+}
+
+void ProcessOnOffUnicastBindingCommand(BindingCommandData * data, const EmberBindingTableEntry & binding,
+                                       OperationalDeviceProxy * peer_device)
+{
+    auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) {
+        ChipLogProgress(NotSpecified, "OnOff command succeeds");
+    };
+
+    auto onFailure = [](CHIP_ERROR error) {
+        ChipLogError(NotSpecified, "OnOff command failed: %" CHIP_ERROR_FORMAT, error.Format());
+    };
+
+    VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady());
+
+    Clusters::OnOff::Commands::Toggle::Type toggleCommand;
+    Clusters::OnOff::Commands::On::Type onCommand;
+    Clusters::OnOff::Commands::Off::Type offCommand;
+    Clusters::OnOff::Commands::OffWithEffect::Type offwitheffectCommand;
+    Clusters::OnOff::Commands::OnWithRecallGlobalScene::Type onwithrecallglobalsceneCommand;
+    Clusters::OnOff::Commands::OnWithTimedOff::Type onwithtimedoffCommand;
+
+    switch (data->commandId)
+    {
+    case Clusters::OnOff::Commands::Toggle::Id:
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         toggleCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::OnOff::Commands::On::Id:
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         onCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::OnOff::Commands::Off::Id:
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         offCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::OnOff::Commands::OffWithEffect::Id:
+        offwitheffectCommand.effectId      = static_cast<EmberAfOnOffEffectIdentifier>(data->args[0]);
+        offwitheffectCommand.effectVariant = static_cast<EmberAfOnOffDelayedAllOffEffectVariant>(data->args[1]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         offwitheffectCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::OnOff::Commands::OnWithRecallGlobalScene::Id:
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         onwithrecallglobalsceneCommand, onSuccess, onFailure);
+        break;
+
+    case Clusters::OnOff::Commands::OnWithTimedOff::Id:
+        onwithtimedoffCommand.onOffControl = static_cast<chip::BitMask<chip::app::Clusters::OnOff::OnOffControl>>(data->args[0]);
+        onwithtimedoffCommand.onTime       = static_cast<uint16_t>(data->args[1]);
+        onwithtimedoffCommand.offWaitTime  = static_cast<uint16_t>(data->args[2]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         onwithtimedoffCommand, onSuccess, onFailure);
+        break;
+    }
+}
+
+void ProcessOnOffGroupBindingCommand(BindingCommandData * data, const EmberBindingTableEntry & binding)
+{
+    Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager();
+
+    Clusters::OnOff::Commands::Toggle::Type toggleCommand;
+    Clusters::OnOff::Commands::On::Type onCommand;
+    Clusters::OnOff::Commands::Off::Type offCommand;
+    Clusters::OnOff::Commands::OffWithEffect::Type offwitheffectCommand;
+    Clusters::OnOff::Commands::OnWithRecallGlobalScene::Type onwithrecallglobalsceneCommand;
+    Clusters::OnOff::Commands::OnWithTimedOff::Type onwithtimedoffCommand;
+
+    switch (data->commandId)
+    {
+    case Clusters::OnOff::Commands::Toggle::Id:
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, toggleCommand);
+        break;
+
+    case Clusters::OnOff::Commands::On::Id:
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, onCommand);
+        break;
+
+    case Clusters::OnOff::Commands::Off::Id:
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, offCommand);
+        break;
+
+    case Clusters::OnOff::Commands::OffWithEffect::Id:
+        offwitheffectCommand.effectId      = static_cast<EmberAfOnOffEffectIdentifier>(data->args[0]);
+        offwitheffectCommand.effectVariant = static_cast<EmberAfOnOffDelayedAllOffEffectVariant>(data->args[1]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, offwitheffectCommand);
+        break;
+
+    case Clusters::OnOff::Commands::OnWithRecallGlobalScene::Id:
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, onwithrecallglobalsceneCommand);
+        break;
+
+    case Clusters::OnOff::Commands::OnWithTimedOff::Id:
+        onwithtimedoffCommand.onOffControl = static_cast<chip::BitMask<chip::app::Clusters::OnOff::OnOffControl>>(data->args[0]);
+        onwithtimedoffCommand.onTime       = static_cast<uint16_t>(data->args[1]);
+        onwithtimedoffCommand.offWaitTime  = static_cast<uint16_t>(data->args[2]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, onwithtimedoffCommand);
+        break;
+    }
+}
+
+#if CONFIG_ENABLE_CHIP_SHELL
+/********************************************************
+ * OnOff switch shell functions
+ *********************************************************/
+
+CHIP_ERROR OnOffHelpHandler(int argc, char ** argv)
+{
+    sShellSwitchOnOffSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OnOffSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc == 0)
+    {
+        return OnOffHelpHandler(argc, argv);
+    }
+
+    return sShellSwitchOnOffSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR OnSwitchCommandHandler(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::OnOff::Commands::On::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OffSwitchCommandHandler(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::OnOff::Commands::Off::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ToggleSwitchCommandHandler(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::OnOff::Commands::Toggle::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OffWithEffectSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 2)
+    {
+        return OnOffHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::OnOff::Commands::OffWithEffect::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OnWithRecallGlobalSceneSwitchCommandHandler(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::OnOff::Commands::OnWithRecallGlobalScene::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OnWithTimedOffSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 3)
+    {
+        return OnOffHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::OnOff::Commands::OnWithTimedOff::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+/********************************************************
+ * OnOff Read switch shell functions
+ *********************************************************/
+
+CHIP_ERROR OnOffReadHelpHandler(int argc, char ** argv)
+{
+    sShellSwitchOnOffReadSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OnOffRead(int argc, char ** argv)
+{
+    if (argc == 0)
+    {
+        return OnOffReadHelpHandler(argc, argv);
+    }
+
+    return sShellSwitchOnOffReadSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR OnOffReadAttributeList(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::OnOff::Attributes::AttributeList::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OnOffReadOnOff(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::OnOff::Attributes::OnOff::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OnOffReadGlobalSceneControl(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::OnOff::Attributes::GlobalSceneControl::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OnOffReadOnTime(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::OnOff::Attributes::OnTime::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OnOffReadOffWaitTime(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::OnOff::Attributes::OffWaitTime::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR OnOffReadStartUpOnOff(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::OnOff::Attributes::StartUpOnOff::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+/********************************************************
+ * Groups OnOff switch shell functions
+ *********************************************************/
+
+CHIP_ERROR GroupsOnOffHelpHandler(int argc, char ** argv)
+{
+    sShellSwitchGroupsOnOffSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsOnOffSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc == 0)
+    {
+        return GroupsOnOffHelpHandler(argc, argv);
+    }
+
+    return sShellSwitchGroupsOnOffSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR GroupOnSwitchCommandHandler(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::OnOff::Commands::On::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupOffSwitchCommandHandler(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::OnOff::Commands::Off::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupToggleSwitchCommandHandler(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::OnOff::Commands::Toggle::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupOffWithEffectSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 2)
+    {
+        return GroupsOnOffHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::OnOff::Commands::OffWithEffect::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupOnWithRecallGlobalSceneSwitchCommandHandler(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::OnOff::Commands::OnWithRecallGlobalScene::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupOnWithTimedOffSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 2)
+    {
+        return GroupsOnOffHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::OnOff::Commands::OnWithTimedOff::Id;
+    data->clusterId           = Clusters::OnOff::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+    data->args[2]             = atoi(argv[2]);
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+#endif // CONFIG_ENABLE_CHIP_SHELL
diff --git a/examples/all-clusters-app/ameba/main/include/ThermostatCommands.h b/examples/all-clusters-app/ameba/main/include/ThermostatCommands.h
new file mode 100644
index 0000000..c1444bf
--- /dev/null
+++ b/examples/all-clusters-app/ameba/main/include/ThermostatCommands.h
@@ -0,0 +1,445 @@
+/*
+ *
+ *    Copyright (c) 2022 Project CHIP Authors
+ *    All rights reserved.
+ *
+ *    Licensed under the Apache License, Version 2.0 (the "License");
+ *    you may not use this file except in compliance with the License.
+ *    You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *    Unless required by applicable law or agreed to in writing, software
+ *    distributed under the License is distributed on an "AS IS" BASIS,
+ *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *    See the License for the specific language governing permissions and
+ *    limitations under the License.
+ */
+
+#include "controller/InvokeInteraction.h"
+#include "controller/ReadInteraction.h"
+#include <app/clusters/bindings/bindings.h>
+
+#if CONFIG_ENABLE_CHIP_SHELL
+#include "lib/shell/Engine.h"
+#include "lib/shell/commands/Help.h"
+#endif // ENABLE_CHIP_SHELL
+
+using namespace chip;
+using namespace chip::app;
+
+#if CONFIG_ENABLE_CHIP_SHELL
+using Shell::Engine;
+using Shell::shell_command_t;
+using Shell::streamer_get;
+using Shell::streamer_printf;
+
+Engine sShellSwitchThermostatSubCommands;
+Engine sShellSwitchThermostatReadSubCommands;
+Engine sShellSwitchGroupsThermostatSubCommands;
+#endif // defined(ENABLE_CHIP_SHELL)
+
+void ProcessThermostatUnicastBindingRead(BindingCommandData * data, const EmberBindingTableEntry & binding,
+                                         OperationalDeviceProxy * peer_device)
+{
+    auto onSuccess = [](const ConcreteDataAttributePath & attributePath, const auto & dataResponse) {
+        ChipLogProgress(NotSpecified, "Read Thermostat attribute succeeds");
+    };
+
+    auto onFailure = [](const ConcreteDataAttributePath * attributePath, CHIP_ERROR error) {
+        ChipLogError(NotSpecified, "Read Thermostat attribute failed: %" CHIP_ERROR_FORMAT, error.Format());
+    };
+
+    VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady());
+
+    switch (data->attributeId)
+    {
+    case Clusters::Thermostat::Attributes::AttributeList::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::AttributeList::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Thermostat::Attributes::LocalTemperature::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::LocalTemperature::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Thermostat::Attributes::AbsMinHeatSetpointLimit::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::AbsMinHeatSetpointLimit::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Thermostat::Attributes::AbsMaxHeatSetpointLimit::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::AbsMaxHeatSetpointLimit::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Thermostat::Attributes::AbsMinCoolSetpointLimit::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::AbsMinCoolSetpointLimit::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Thermostat::Attributes::AbsMaxCoolSetpointLimit::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::AbsMaxCoolSetpointLimit::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Thermostat::Attributes::PICoolingDemand::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::PICoolingDemand::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Thermostat::Attributes::PIHeatingDemand::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::PIHeatingDemand::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Thermostat::Attributes::OccupiedCoolingSetpoint::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::OccupiedCoolingSetpoint::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Thermostat::Attributes::OccupiedHeatingSetpoint::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::OccupiedHeatingSetpoint::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Thermostat::Attributes::MinHeatSetpointLimit::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::MinHeatSetpointLimit::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Thermostat::Attributes::MaxHeatSetpointLimit::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::MaxHeatSetpointLimit::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Thermostat::Attributes::MinCoolSetpointLimit::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::MinCoolSetpointLimit::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Thermostat::Attributes::MaxCoolSetpointLimit::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::MaxCoolSetpointLimit::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Thermostat::Attributes::ControlSequenceOfOperation::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::ControlSequenceOfOperation::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+
+    case Clusters::Thermostat::Attributes::SystemMode::Id:
+        Controller::ReadAttribute<Clusters::Thermostat::Attributes::SystemMode::TypeInfo>(
+            peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure);
+        break;
+    }
+}
+
+void ProcessThermostatUnicastBindingCommand(BindingCommandData * data, const EmberBindingTableEntry & binding,
+                                            OperationalDeviceProxy * peer_device)
+{
+    auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) {
+        ChipLogProgress(NotSpecified, "Thermostat command succeeds");
+    };
+
+    auto onFailure = [](CHIP_ERROR error) {
+        ChipLogError(NotSpecified, "Thermostat command failed: %" CHIP_ERROR_FORMAT, error.Format());
+    };
+
+    VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady());
+
+    Clusters::Thermostat::Commands::SetpointRaiseLower::Type setpointRaiseLowerCommand;
+
+    switch (data->commandId)
+    {
+    case Clusters::Thermostat::Commands::SetpointRaiseLower::Id:
+        setpointRaiseLowerCommand.mode   = static_cast<EmberAfSetpointAdjustMode>(data->args[0]);
+        setpointRaiseLowerCommand.amount = static_cast<int8_t>(data->args[1]);
+        Controller::InvokeCommandRequest(peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote,
+                                         setpointRaiseLowerCommand, onSuccess, onFailure);
+        break;
+    }
+}
+
+void ProcessThermostatGroupBindingCommand(BindingCommandData * data, const EmberBindingTableEntry & binding)
+{
+    Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager();
+
+    Clusters::Thermostat::Commands::SetpointRaiseLower::Type setpointRaiseLowerCommand;
+
+    switch (data->commandId)
+    {
+    case Clusters::Thermostat::Commands::SetpointRaiseLower::Id:
+        setpointRaiseLowerCommand.mode   = static_cast<EmberAfSetpointAdjustMode>(data->args[0]);
+        setpointRaiseLowerCommand.amount = static_cast<int8_t>(data->args[1]);
+        Controller::InvokeGroupCommandRequest(&exchangeMgr, binding.fabricIndex, binding.groupId, setpointRaiseLowerCommand);
+        break;
+    }
+}
+
+#if CONFIG_ENABLE_CHIP_SHELL
+/********************************************************
+ * Thermostat switch shell functions
+ *********************************************************/
+
+CHIP_ERROR ThermostatHelpHandler(int argc, char ** argv)
+{
+    sShellSwitchThermostatSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc == 0)
+    {
+        return ThermostatHelpHandler(argc, argv);
+    }
+
+    return sShellSwitchThermostatSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR SetpointRaiseLowerSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc != 2)
+    {
+        return ThermostatHelpHandler(argc, argv);
+    }
+
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::Thermostat::Commands::SetpointRaiseLower::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->args[0]             = atoi(argv[0]);
+    data->args[1]             = atoi(argv[1]);
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+/********************************************************
+ * Thermostat Read switch shell functions
+ *********************************************************/
+
+CHIP_ERROR ThermostatReadHelpHandler(int argc, char ** argv)
+{
+    sShellSwitchThermostatReadSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatRead(int argc, char ** argv)
+{
+    if (argc == 0)
+    {
+        return ThermostatReadHelpHandler(argc, argv);
+    }
+
+    return sShellSwitchThermostatReadSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR ThermostatReadAttributeList(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::AttributeList::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatReadLocalTemperature(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::LocalTemperature::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatReadAbsMinHeatSetpointLimit(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::AbsMinHeatSetpointLimit::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatReadAbsMaxHeatSetpointLimit(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::AbsMaxHeatSetpointLimit::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatReadAbsMinCoolSetpointLimit(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::AbsMinCoolSetpointLimit::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatReadAbsMaxCoolSetpointLimit(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::AbsMaxCoolSetpointLimit::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatReadPiCoolingDemand(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::PICoolingDemand::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatReadPiHeatingDemand(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::PIHeatingDemand::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatReadOccupiedCoolingSetpoint(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::OccupiedCoolingSetpoint::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatReadOccupiedHeatingSetpoint(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::OccupiedHeatingSetpoint::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatReadMinHeatSetpointLimit(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::MinHeatSetpointLimit::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatReadMaxHeatSetpointLimit(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::MaxHeatSetpointLimit::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatReadMinCoolSetpointLimit(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::MinCoolSetpointLimit::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatReadMaxCoolSetpointLimit(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::MaxCoolSetpointLimit::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatReadControlSequenceOfOperation(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::ControlSequenceOfOperation::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR ThermostatReadSystemMode(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->attributeId         = Clusters::Thermostat::Attributes::SystemMode::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isReadAttribute     = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+
+/********************************************************
+ * Groups Thermostat switch shell functions
+ *********************************************************/
+
+CHIP_ERROR GroupsThermostatHelpHandler(int argc, char ** argv)
+{
+    sShellSwitchGroupsThermostatSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr);
+    return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR GroupsThermostatSwitchCommandHandler(int argc, char ** argv)
+{
+    if (argc == 0)
+    {
+        return GroupsThermostatHelpHandler(argc, argv);
+    }
+
+    return sShellSwitchGroupsThermostatSubCommands.ExecCommand(argc, argv);
+}
+
+CHIP_ERROR GroupsSetpointRaiseLowerSwitchCommandHandler(int argc, char ** argv)
+{
+    BindingCommandData * data = Platform::New<BindingCommandData>();
+    data->commandId           = Clusters::Thermostat::Commands::SetpointRaiseLower::Id;
+    data->clusterId           = Clusters::Thermostat::Id;
+    data->isGroup             = true;
+
+    DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast<intptr_t>(data));
+    return CHIP_NO_ERROR;
+}
+#endif // CONFIG_ENABLE_CHIP_SHELL