From 33b90460266960172d554851840b55a9522f6b7e Mon Sep 17 00:00:00 2001 From: pankore <86098180+pankore@users.noreply.github.com> Date: Wed, 23 Nov 2022 22:52:29 +0800 Subject: [PATCH] [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 --- config/ameba/chip.cmake | 1 + examples/all-clusters-app/ameba/README.md | 49 +- .../all-clusters-app/ameba/chip_main.cmake | 1 + .../ameba/main/BindingHandler.cpp | 591 +++-- .../ameba/main/include/BindingHandler.h | 6 +- .../ameba/main/include/ColorControlCommands.h | 2159 +++++++++++++++++ .../ameba/main/include/IdentifyCommand.h | 270 +++ .../ameba/main/include/LevelControlCommands.h | 843 +++++++ .../ameba/main/include/OnOffCommands.h | 474 ++++ .../ameba/main/include/ThermostatCommands.h | 445 ++++ 10 files changed, 4641 insertions(+), 198 deletions(-) create mode 100644 examples/all-clusters-app/ameba/main/include/ColorControlCommands.h create mode 100644 examples/all-clusters-app/ameba/main/include/IdentifyCommand.h create mode 100644 examples/all-clusters-app/ameba/main/include/LevelControlCommands.h create mode 100644 examples/all-clusters-app/ameba/main/include/OnOffCommands.h create mode 100644 examples/all-clusters-app/ameba/main/include/ThermostatCommands.h diff --git a/config/ameba/chip.cmake b/config/ameba/chip.cmake index a6e696882a0c9d..515bff64ef99c9 100644 --- a/config/ameba/chip.cmake +++ b/config/ameba/chip.cmake @@ -30,6 +30,7 @@ list( -DCHIP_DEVICE_LAYER_TARGET=Ameba -DMBEDTLS_CONFIG_FILE= -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 ddbdf66ecf9a9d..a710a2e5e006f9 100644 --- a/examples/all-clusters-app/ameba/README.md +++ b/examples/all-clusters-app/ameba/README.md @@ -14,7 +14,7 @@ control. - [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 @@ to be On or Off. - 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 20202021 3840 $ ./chip-tool pairing ble-wifi 2 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` + +* 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 onoff on - > switch onoff off + `switch read ` diff --git a/examples/all-clusters-app/ameba/chip_main.cmake b/examples/all-clusters-app/ameba/chip_main.cmake index 35d0b2877e3788..50d0d2d76ca9c1 100755 --- a/examples/all-clusters-app/ameba/chip_main.cmake +++ b/examples/all-clusters-app/ameba/chip_main.cmake @@ -255,6 +255,7 @@ list( -DUSE_ZAP_CONFIG -DCHIP_HAVE_CONFIG_H -DMBEDTLS_CONFIG_FILE= + -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 29acdaae952896..64ccb619a2edf5 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 #include @@ -40,95 +45,84 @@ using Shell::streamer_get; 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(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 @@ void InitBindingHandlerInternal(intptr_t arg) chip::BindingManager::GetInstance().RegisterBoundDeviceContextReleaseHandler(LightSwitchContextReleaseHandler); } -#ifdef CONFIG_ENABLE_CHIP_SHELL +#if CONFIG_ENABLE_CHIP_SHELL /******************************************************** * Switch shell functions @@ -171,56 +165,6 @@ CHIP_ERROR SwitchCommandHandler(int argc, char ** argv) return sShellSwitchSubCommands.ExecCommand(argc, argv); } -/******************************************************** - * 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(); - data->commandId = Clusters::OnOff::Commands::On::Id; - data->clusterId = Clusters::OnOff::Id; - - DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); - return CHIP_NO_ERROR; -} - -CHIP_ERROR OffSwitchCommandHandler(int argc, char ** argv) -{ - BindingCommandData * data = Platform::New(); - data->commandId = Clusters::OnOff::Commands::Off::Id; - data->clusterId = Clusters::OnOff::Id; - - DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); - return CHIP_NO_ERROR; -} - -CHIP_ERROR ToggleSwitchCommandHandler(int argc, char ** argv) -{ - BindingCommandData * data = Platform::New(); - data->commandId = Clusters::OnOff::Commands::Toggle::Id; - data->clusterId = Clusters::OnOff::Id; - - DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); - return CHIP_NO_ERROR; -} - /******************************************************** * bind switch shell functions *********************************************************/ @@ -292,59 +236,6 @@ CHIP_ERROR GroupsSwitchCommandHandler(int argc, char ** argv) 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(); - data->commandId = Clusters::OnOff::Commands::On::Id; - data->clusterId = Clusters::OnOff::Id; - data->isGroup = true; - - DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); - return CHIP_NO_ERROR; -} - -CHIP_ERROR GroupOffSwitchCommandHandler(int argc, char ** argv) -{ - BindingCommandData * data = Platform::New(); - data->commandId = Clusters::OnOff::Commands::Off::Id; - data->clusterId = Clusters::OnOff::Id; - data->isGroup = true; - - DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); - return CHIP_NO_ERROR; -} - -CHIP_ERROR GroupToggleSwitchCommandHandler(int argc, char ** argv) -{ - BindingCommandData * data = Platform::New(); - data->commandId = Clusters::OnOff::Commands::Toggle::Id; - data->clusterId = Clusters::OnOff::Id; - data->isGroup = true; - - DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data)); - return CHIP_NO_ERROR; -} - /** * @brief configures switch matter shell * @@ -354,27 +245,332 @@ static void RegisterSwitchCommands() static const shell_command_t sSwitchSubCommands[] = { { &SwitchHelpHandler, "help", "Usage: switch " }, + { &IdentifySwitchCommandHandler, "identify", " Usage: switch identify " }, { &OnOffSwitchCommandHandler, "onoff", " Usage: switch onoff " }, + { &LevelControlSwitchCommandHandler, "levelcontrol", " Usage: switch levlecontrol " }, + { &ColorControlSwitchCommandHandler, "colorcontrol", " Usage: switch colorcontrol " }, + { &ThermostatSwitchCommandHandler, "thermostat", " Usage: switch thermostat " }, { &GroupsSwitchCommandHandler, "groups", "Usage: switch groups " }, { &BindingSwitchCommandHandler, "binding", "Usage: switch binding " } }; + static const shell_command_t sSwitchIdentifySubCommands[] = { + { &IdentifyHelpHandler, "help", "Usage: switch identify " }, + { &IdentifyCommandHandler, "identify", "identify Usage: switch identify identify" }, + { &TriggerEffectSwitchCommandHandler, "triggereffect", "triggereffect Usage: switch identify triggereffect" }, + { &IdentifyRead, "read", "Usage : switch identify read " } + }; + + static const shell_command_t sSwitchIdentifyReadSubCommands[] = { + { &IdentifyReadHelpHandler, "help", "Usage : switch identify read " }, + { &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 " }, - { &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" } + { &OnOffHelpHandler, "help", "Usage: switch ononff " }, + { &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 " }, + { &OnWithRecallGlobalSceneSwitchCommandHandler, "onWRGS", "on-with-recall-global-scene Usage: switch onoff onWRGS" }, + { &OnWithTimedOffSwitchCommandHandler, "onWTO", + "on-with-timed-off Usage: switch onoff onWTO " }, + { &OnOffRead, "read", "Usage : switch onoff read " } + }; + + static const shell_command_t sSwitchOnOffReadSubCommands[] = { + { &OnOffReadHelpHandler, "help", "Usage : switch ononff read " }, + { &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 " }, + { &MoveToLevelSwitchCommandHandler, "movetolevel", + "movetolevel Usage: switch levelcontrol movetolevel " }, + { &MoveSwitchCommandHandler, "move", + "move Usage: switch levelcontrol move " }, + { &StepSwitchCommandHandler, "step", + "step Usage: switch levelcontrol step " }, + { &StopSwitchCommandHandler, "stop", "step Usage: switch levelcontrol stop " }, + { &MoveToLevelWithOnOffSwitchCommandHandler, "MTLWOO", + "movetolevelwithonoff Usage: switch levelcontrol MTLWOO " }, + { &MoveWithOnOffSwitchCommandHandler, "MWOO", + "movewithonoff Usage: switch levelcontrol MWOO " }, + { &StepWithOnOffSwitchCommandHandler, "stepWOO", + "stepwithonoff Usage: switch levelcontrol stepWOO " + "" }, + { &StopWithOnOffSwitchCommandHandler, "stopWOO", + "stopwithonoff Usage: switch levelcontrol stopWOO " }, + { &LevelControlRead, "read", "Usage : switch levelcontrol read " } + }; + + static const shell_command_t sSwitchLevelControlReadSubCommands[] = { + { &LevelControlReadHelpHandler, "help", "Usage : switch levelcontrol read " }, + { &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 sSwitchGroupsSubCommands[] = { { &GroupsHelpHandler, "help", "Usage: switch groups " }, - { &GroupsOnOffSwitchCommandHandler, "onoff", - "Usage: switch groups onoff " } }; + static const shell_command_t sSwitchColorControlSubCommands[] = { + { &ColorControlHelpHandler, "help", "Usage: switch colorcontrol " }, + { &MoveToHueCommandHandler, "movetohue", + "movetohue Usage: switch colorcontrol movetohue " }, + { &MoveHueCommandHandler, "movehue", + "movehue Usage: switch colorcontrol movehue " }, + { &StepHueCommandHandler, "stephue", + "stephue Usage: switch colorcontrol stephue " }, + { &MoveToSaturationCommandHandler, "movetosat", + "movetosaturation Usage: switch colorcontrol movetosat " }, + { &MoveSaturationCommandHandler, "movesat", + "movesaturation Usage: switch colorcontrol movesat " }, + { &StepSaturationCommandHandler, "stepsat", + "stepsaturation Usage: switch colorcontrol stepsat " + "" }, + { &MoveToHueAndSaturationCommandHandler, "movetoHS", + "movetohueandsaturation Usage: switch colorcontrol movetoHS " + "" }, + { &MoveToColorCommandHandler, "movetocolor", + "movetocolor Usage: switch colorcontrol movetocolor " }, + { &MoveColorCommandHandler, "movecolor", + "movecolor Usage: switch colorcontrol movecolor " }, + { &StepColorCommandHandler, "stepcolor", + "stepcolor Usage: switch colorcontrol stepcolor " }, + { &MoveToColorTemperatureCommandHandler, "movetoCT", + "movetocolortemperature Usage: switch colorcontrol movetoCT " + "" }, + { &EnhancedMoveToHueCommandHandler, "Emovetohue", + "enhancedmovetohue Usage: switch colorcontrol Emovetohue " + "" }, + { &EnhancedMoveHueCommandHandler, "Emovehue", + "enhancedmovehue Usage: switch colorcontrol Emovehue " }, + { &EnhancedStepHueCommandHandler, "Estephue", + "enhancedstephue Usage: switch colorcontrol Estephue " + "" }, + { &EnhancedMoveToHueAndSaturationCommandHandler, "EmovetoHS", + "enhancedmovetohueandsaturation Usage: switch colorcontrol EmovetoHS " + " " }, + { &ColorLoopSetCommandHandler, "colorloopset", + "colorloopset Usage: switch colorcontrol colorloopset