diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter index be3eac6f3db982..d53b2df3f5d5e0 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter @@ -5643,6 +5643,65 @@ provisional cluster BallastConfiguration = 769 { readonly attribute int16u clusterRevision = 65533; } +/** This cluster provides a means to activate and control dynamic lighting effects on a light. */ +provisional cluster DynamicLighting = 773 { + revision 1; + + enum EffectColorModeEnum : enum8 { + kLevel = 0; + kXY = 1 [spec_name = "XY"]; + kXYAndLevel = 2; + kHS = 3 [spec_name = "HS"]; + kHSAndLevel = 4; + kEHUE = 5 [spec_name = "EHUE"]; + kEHUEAndLevel = 6; + } + + enum EffectSourceEnum : enum8 { + kInternal = 0; + kSoundBased = 1; + } + + struct EffectColorStruct { + nullable int8u level = 0; + nullable int16u x = 1; + nullable int16u y = 2; + nullable int8u hue = 3; + nullable int16u enhancedHue = 4; + nullable int8u saturation = 5; + } + + struct EffectStruct { + int16u effectID = 0; + EffectSourceEnum source = 1; + char_string<32> label = 2; + int16u maxSpeed = 3; + int16u defaultSpeed = 4; + boolean supportsColorPalette = 5; + } + + readonly attribute EffectStruct availableEffects[] = 0; + readonly attribute nullable int16u currentEffectID = 1; + attribute nullable int16u currentSpeed = 2; + readonly attribute command_id generatedCommandList[] = 65528; + readonly attribute command_id acceptedCommandList[] = 65529; + readonly attribute attrib_id attributeList[] = 65531; + readonly attribute bitmap32 featureMap = 65532; + readonly attribute int16u clusterRevision = 65533; + + request struct StartEffectRequest { + int16u effectID = 0; + int16u speed = 1; + nullable EffectColorModeEnum colorMode = 2; + nullable EffectColorStruct colorPalette[] = 3; + } + + /** This command will start the specified effect. */ + command StartEffect(StartEffectRequest): DefaultSuccess = 0; + /** This command will stop the current effect. */ + command StopEffect(): DefaultSuccess = 1; +} + /** Attributes and commands for configuring the measurement of illuminance, and reporting illuminance measurements. */ cluster IlluminanceMeasurement = 1024 { revision 3; @@ -8506,6 +8565,20 @@ endpoint 1 { ram attribute clusterRevision default = 4; } + server cluster DynamicLighting { + callback attribute availableEffects; + callback attribute currentEffectID; + callback attribute currentSpeed; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute attributeList; + callback attribute featureMap; + callback attribute clusterRevision; + + handle command StartEffect; + handle command StopEffect; + } + server cluster IlluminanceMeasurement { callback attribute measuredValue; ram attribute minMeasuredValue default = 0x01; diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap index 43f0839c42ac86..d823c036cada6f 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -16299,6 +16299,162 @@ } ] }, + { + "name": "Dynamic Lighting", + "code": 773, + "mfgCode": null, + "define": "DYNAMIC_LIGHTING_CLUSTER", + "side": "server", + "enabled": 1, + "commands": [ + { + "name": "StartEffect", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "StopEffect", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "AvailableEffects", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentEffectID", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "CurrentSpeed", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + }, + { + "name": "GeneratedCommandList", + "code": 65528, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AcceptedCommandList", + "code": 65529, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AttributeList", + "code": 65531, + "mfgCode": null, + "side": "server", + "type": "array", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "FeatureMap", + "code": 65532, + "mfgCode": null, + "side": "server", + "type": "bitmap32", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ClusterRevision", + "code": 65533, + "mfgCode": null, + "side": "server", + "type": "int16u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "reportable": 1, + "minInterval": 0, + "maxInterval": 65344, + "reportableChange": 0 + } + ] + }, { "name": "Temperature Measurement", "code": 1026, @@ -24496,4 +24652,4 @@ "parentEndpointIdentifier": null } ] -} \ No newline at end of file +} diff --git a/src/BUILD.gn b/src/BUILD.gn index 3bac4f2cc2b0ae..efdbfa940b7d8e 100644 --- a/src/BUILD.gn +++ b/src/BUILD.gn @@ -76,6 +76,7 @@ if (chip_build_tests) { "${chip_root}/src/app/clusters/concentration-measurement-server/tests", "${chip_root}/src/app/clusters/descriptor/tests", "${chip_root}/src/app/clusters/device-energy-management-server/tests", + "${chip_root}/src/app/clusters/dynamic-lighting-server/tests", "${chip_root}/src/app/clusters/electrical-energy-measurement-server/tests", "${chip_root}/src/app/clusters/electrical-power-measurement-server/tests", "${chip_root}/src/app/clusters/ethernet-network-diagnostics-server/tests", diff --git a/src/app/clusters/BUILD.gn b/src/app/clusters/BUILD.gn index a23652de9208a5..521cc9932933a9 100644 --- a/src/app/clusters/BUILD.gn +++ b/src/app/clusters/BUILD.gn @@ -37,6 +37,7 @@ source_set("clusters") { "concentration-measurement-server", "descriptor", "device-energy-management-server", + "dynamic-lighting-server", "fan-control-server", "flow-measurement-server", "general-commissioning-server", diff --git a/src/app/clusters/dynamic-lighting-server/BUILD.gn b/src/app/clusters/dynamic-lighting-server/BUILD.gn new file mode 100644 index 00000000000000..5d19b39dea325a --- /dev/null +++ b/src/app/clusters/dynamic-lighting-server/BUILD.gn @@ -0,0 +1,30 @@ +# Copyright (c) 2026 Project CHIP Authors +# +# 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. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") + +source_set("dynamic-lighting-server") { + sources = [ + "DynamicLightingCluster.cpp", + "DynamicLightingCluster.h", + ] + + public_deps = [ + "${chip_root}/src/app/data-model-provider", + "${chip_root}/src/app/server", + "${chip_root}/src/app/server-cluster", + "${chip_root}/zzz_generated/app-common/clusters/DynamicLighting", + ] +} diff --git a/src/app/clusters/dynamic-lighting-server/CodegenIntegration.cpp b/src/app/clusters/dynamic-lighting-server/CodegenIntegration.cpp new file mode 100644 index 00000000000000..097c19c5bbbcbc --- /dev/null +++ b/src/app/clusters/dynamic-lighting-server/CodegenIntegration.cpp @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2026 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 +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::DynamicLighting; + +namespace { + +constexpr size_t kDynamicLightingFixedClusterCount = DynamicLighting::StaticApplicationConfig::kFixedClusterConfig.size(); +constexpr size_t kDynamicLightingMaxClusterCount = kDynamicLightingFixedClusterCount + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; + +LazyRegisteredServerCluster gServers[kDynamicLightingMaxClusterCount]; + +class IntegrationDelegate : public CodegenClusterIntegration::Delegate +{ +public: + ServerClusterRegistration & CreateRegistration(EndpointId endpointId, unsigned clusterInstanceIndex, + uint32_t optionalAttributeBits, uint32_t featureMap) override + { + VerifyOrDie(clusterInstanceIndex < kDynamicLightingMaxClusterCount); + + gServers[clusterInstanceIndex].Create(endpointId); + return gServers[clusterInstanceIndex].Registration(); + } + + ServerClusterInterface * FindRegistration(unsigned clusterInstanceIndex) override + { + VerifyOrReturnValue(clusterInstanceIndex < kDynamicLightingMaxClusterCount, nullptr); + VerifyOrReturnValue(gServers[clusterInstanceIndex].IsConstructed(), nullptr); + return &gServers[clusterInstanceIndex].Cluster(); + } + + void ReleaseRegistration(unsigned clusterInstanceIndex) override + { + VerifyOrReturn(clusterInstanceIndex < kDynamicLightingMaxClusterCount); + + gServers[clusterInstanceIndex].Destroy(); + } +}; + +} // namespace + +void MatterDynamicLightingClusterInitCallback(EndpointId endpointId) +{ + IntegrationDelegate integrationDelegate; + + CodegenClusterIntegration::RegisterServer( + { + .endpointId = endpointId, + .clusterId = DynamicLighting::Id, + .fixedClusterInstanceCount = kDynamicLightingFixedClusterCount, + .maxClusterInstanceCount = kDynamicLightingMaxClusterCount, + .fetchFeatureMap = false, + .fetchOptionalAttributes = false, + }, + integrationDelegate); +} + +void MatterDynamicLightingClusterShutdownCallback(EndpointId endpointId, MatterClusterShutdownType shutdownType) +{ + IntegrationDelegate integrationDelegate; + + CodegenClusterIntegration::UnregisterServer( + { + .endpointId = endpointId, + .clusterId = DynamicLighting::Id, + .fixedClusterInstanceCount = kDynamicLightingFixedClusterCount, + .maxClusterInstanceCount = kDynamicLightingMaxClusterCount, + }, + integrationDelegate, shutdownType); +} + +void MatterDynamicLightingPluginServerInitCallback() {} diff --git a/src/app/clusters/dynamic-lighting-server/CodegenIntegration.h b/src/app/clusters/dynamic-lighting-server/CodegenIntegration.h new file mode 100644 index 00000000000000..71b529f78bc862 --- /dev/null +++ b/src/app/clusters/dynamic-lighting-server/CodegenIntegration.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2026 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. + */ + +#pragma once + +#include diff --git a/src/app/clusters/dynamic-lighting-server/DynamicLightingCluster.cpp b/src/app/clusters/dynamic-lighting-server/DynamicLightingCluster.cpp new file mode 100644 index 00000000000000..10bcbd99cee4a1 --- /dev/null +++ b/src/app/clusters/dynamic-lighting-server/DynamicLightingCluster.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2026 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 +#include +#include +#include + +namespace chip::app::Clusters { + +using namespace DynamicLighting; +using namespace DynamicLighting::Attributes; + +DynamicLightingCluster::DynamicLightingCluster(EndpointId endpointId) : DefaultServerCluster({ endpointId, DynamicLighting::Id }) {} + +DataModel::ActionReturnStatus DynamicLightingCluster::ReadAttribute(const DataModel::ReadAttributeRequest & request, + AttributeValueEncoder & encoder) +{ + switch (request.path.mAttributeId) + { + case ClusterRevision::Id: + return encoder.Encode(DynamicLighting::kRevision); + case FeatureMap::Id: + return encoder.Encode(static_cast(0)); + case AvailableEffects::Id: + return encoder.EncodeEmptyList(); + case CurrentEffectID::Id: + return encoder.Encode(DataModel::Nullable{ DataModel::NullNullable }); + case CurrentSpeed::Id: + return encoder.Encode(DataModel::Nullable{ DataModel::NullNullable }); + default: + return Protocols::InteractionModel::Status::UnsupportedAttribute; + } +} + +DataModel::ActionReturnStatus DynamicLightingCluster::WriteAttribute(const DataModel::WriteAttributeRequest & request, + AttributeValueDecoder & decoder) +{ + switch (request.path.mAttributeId) + { + case CurrentSpeed::Id: + return Protocols::InteractionModel::Status::InvalidInState; + default: + return DefaultServerCluster::WriteAttribute(request, decoder); + } +} + +CHIP_ERROR DynamicLightingCluster::Attributes(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) +{ + AttributeListBuilder listBuilder(builder); + return listBuilder.Append(Span(DynamicLighting::Attributes::kMandatoryMetadata), {}); +} + +std::optional DynamicLightingCluster::InvokeCommand(const DataModel::InvokeRequest & request, + chip::TLV::TLVReader & input_arguments, + CommandHandler * handler) +{ + switch (request.path.mCommandId) + { + case Commands::StartEffect::Id: + case Commands::StopEffect::Id: + return Protocols::InteractionModel::Status::InvalidCommand; + default: + return DefaultServerCluster::InvokeCommand(request, input_arguments, handler); + } +} + +CHIP_ERROR DynamicLightingCluster::AcceptedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) +{ + return builder.AppendElements({ + Commands::StartEffect::kMetadataEntry, + Commands::StopEffect::kMetadataEntry, + }); +} + +} // namespace chip::app::Clusters diff --git a/src/app/clusters/dynamic-lighting-server/DynamicLightingCluster.h b/src/app/clusters/dynamic-lighting-server/DynamicLightingCluster.h new file mode 100644 index 00000000000000..5c0f6242577a36 --- /dev/null +++ b/src/app/clusters/dynamic-lighting-server/DynamicLightingCluster.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2026 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. + */ +#pragma once + +#include + +namespace chip::app::Clusters { + +class DynamicLightingCluster : public DefaultServerCluster +{ +public: + DynamicLightingCluster(EndpointId endpointId); + + DataModel::ActionReturnStatus ReadAttribute(const DataModel::ReadAttributeRequest & request, + AttributeValueEncoder & encoder) override; + DataModel::ActionReturnStatus WriteAttribute(const DataModel::WriteAttributeRequest & request, + AttributeValueDecoder & decoder) override; + CHIP_ERROR Attributes(const ConcreteClusterPath & path, ReadOnlyBufferBuilder & builder) override; + std::optional InvokeCommand(const DataModel::InvokeRequest & request, + chip::TLV::TLVReader & input_arguments, + CommandHandler * handler) override; + CHIP_ERROR AcceptedCommands(const ConcreteClusterPath & path, + ReadOnlyBufferBuilder & builder) override; +}; + +} // namespace chip::app::Clusters diff --git a/src/app/clusters/dynamic-lighting-server/app_config_dependent_sources.cmake b/src/app/clusters/dynamic-lighting-server/app_config_dependent_sources.cmake new file mode 100644 index 00000000000000..5a181229a8a35d --- /dev/null +++ b/src/app/clusters/dynamic-lighting-server/app_config_dependent_sources.cmake @@ -0,0 +1,21 @@ +# Copyright (c) 2026 Project CHIP Authors +# +# 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. + +# This is the equivalent to app_config_dependent_sources.gni +TARGET_SOURCES( + ${APP_TARGET} + PRIVATE + "${CLUSTER_DIR}/CodegenIntegration.cpp" + "${CLUSTER_DIR}/CodegenIntegration.h" +) diff --git a/src/app/clusters/dynamic-lighting-server/app_config_dependent_sources.gni b/src/app/clusters/dynamic-lighting-server/app_config_dependent_sources.gni new file mode 100644 index 00000000000000..14736492f9c8ca --- /dev/null +++ b/src/app/clusters/dynamic-lighting-server/app_config_dependent_sources.gni @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Project CHIP Authors +# +# 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. + +app_config_dependent_sources = [ + "CodegenIntegration.cpp", + "CodegenIntegration.h", +] diff --git a/src/app/clusters/dynamic-lighting-server/tests/BUILD.gn b/src/app/clusters/dynamic-lighting-server/tests/BUILD.gn new file mode 100644 index 00000000000000..6b6a7dd2cb0a7d --- /dev/null +++ b/src/app/clusters/dynamic-lighting-server/tests/BUILD.gn @@ -0,0 +1,31 @@ +# Copyright (c) 2026 Project CHIP Authors +# +# 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. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") +import("//build_overrides/pigweed.gni") + +import("${chip_root}/build/chip/chip_test_suite.gni") + +chip_test_suite("tests") { + output_name = "libTestDynamicLightingCluster" + + test_sources = [ "TestDynamicLightingCluster.cpp" ] + + public_deps = [ + "${chip_root}/src/app/clusters/dynamic-lighting-server", + "${chip_root}/src/app/server-cluster/testing", + "${chip_root}/src/lib/support", + ] +} diff --git a/src/app/clusters/dynamic-lighting-server/tests/TestDynamicLightingCluster.cpp b/src/app/clusters/dynamic-lighting-server/tests/TestDynamicLightingCluster.cpp new file mode 100644 index 00000000000000..dfc6692578c083 --- /dev/null +++ b/src/app/clusters/dynamic-lighting-server/tests/TestDynamicLightingCluster.cpp @@ -0,0 +1,173 @@ +/* + * + * Copyright (c) 2026 Project CHIP Authors + * + * 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 +#include + +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::DynamicLighting; +using namespace chip::Testing; + +namespace { + +using Protocols::InteractionModel::ClusterStatusCode; +using Protocols::InteractionModel::Status; + +struct TestDynamicLightingCluster : public ::testing::Test +{ + static void SetUpTestSuite() { ASSERT_EQ(Platform::MemoryInit(), CHIP_NO_ERROR); } + static void TearDownTestSuite() { Platform::MemoryShutdown(); } + + TestDynamicLightingCluster() : cluster(kRootEndpointId) {} + + void SetUp() override { ASSERT_EQ(cluster.Startup(testContext.Get()), CHIP_NO_ERROR); } + void TearDown() override { cluster.Shutdown(ClusterShutdownType::kClusterShutdown); } + + TestServerClusterContext testContext; + DynamicLightingCluster cluster; +}; + +} // namespace + +TEST_F(TestDynamicLightingCluster, AttributeList) +{ + ASSERT_TRUE(IsAttributesListEqualTo(cluster, + { + Attributes::AvailableEffects::kMetadataEntry, + Attributes::CurrentEffectID::kMetadataEntry, + Attributes::CurrentSpeed::kMetadataEntry, + })); +} + +TEST_F(TestDynamicLightingCluster, AcceptedCommands) +{ + ASSERT_TRUE(IsAcceptedCommandsListEqualTo(cluster, + { + Commands::StartEffect::kMetadataEntry, + Commands::StopEffect::kMetadataEntry, + })); +} + +TEST_F(TestDynamicLightingCluster, ReadPlaceholderAttributes) +{ + ClusterTester tester(cluster); + + uint16_t clusterRevision{}; + ASSERT_EQ(tester.ReadAttribute(Attributes::ClusterRevision::Id, clusterRevision), CHIP_NO_ERROR); + EXPECT_EQ(clusterRevision, kRevision); + + uint32_t featureMap = 1; + ASSERT_EQ(tester.ReadAttribute(Attributes::FeatureMap::Id, featureMap), CHIP_NO_ERROR); + EXPECT_EQ(featureMap, 0u); + + Attributes::AvailableEffects::TypeInfo::DecodableType availableEffects; + ASSERT_EQ(tester.ReadAttribute(Attributes::AvailableEffects::Id, availableEffects), CHIP_NO_ERROR); + auto effectIterator = availableEffects.begin(); + ASSERT_FALSE(effectIterator.Next()); + + Attributes::CurrentEffectID::TypeInfo::DecodableType currentEffectId; + ASSERT_EQ(tester.ReadAttribute(Attributes::CurrentEffectID::Id, currentEffectId), CHIP_NO_ERROR); + EXPECT_TRUE(currentEffectId.IsNull()); + + Attributes::CurrentSpeed::TypeInfo::DecodableType currentSpeed; + ASSERT_EQ(tester.ReadAttribute(Attributes::CurrentSpeed::Id, currentSpeed), CHIP_NO_ERROR); + EXPECT_TRUE(currentSpeed.IsNull()); +} + +TEST_F(TestDynamicLightingCluster, WriteCurrentSpeedWithNoRunningEffect) +{ + ClusterTester tester(cluster); + + EXPECT_EQ(tester.WriteAttribute(Attributes::CurrentSpeed::Id, static_cast(1)), + Protocols::InteractionModel::Status::InvalidInState); +} + +TEST_F(TestDynamicLightingCluster, ReadUnsupportedAttribute) +{ + constexpr AttributeId kUnsupportedAttributeId = 0xFFF0; + + ReadOperation readOperation(kRootEndpointId, DynamicLighting::Id, kUnsupportedAttributeId); + std::unique_ptr encoder = readOperation.StartEncoding(); + + EXPECT_EQ(cluster.ReadAttribute(readOperation.GetRequest(), *encoder), + Protocols::InteractionModel::Status::UnsupportedAttribute); +} + +TEST_F(TestDynamicLightingCluster, WriteUnsupportedAttribute) +{ + constexpr AttributeId kUnsupportedAttributeId = 0xFFF0; + + WriteOperation writeOperation(kRootEndpointId, DynamicLighting::Id, kUnsupportedAttributeId); + AttributeValueDecoder decoder = writeOperation.DecoderFor(static_cast(1)); + + EXPECT_EQ(cluster.WriteAttribute(writeOperation.GetRequest(), decoder), Protocols::InteractionModel::Status::UnsupportedWrite); +} + +TEST_F(TestDynamicLightingCluster, InvokeStartEffectWithNoAvailableEffects) +{ + ClusterTester tester(cluster); + + Commands::StartEffect::Type request; + request.effectID = 1; + request.speed = 1; + + auto result = tester.Invoke(request); + EXPECT_EQ(result.GetStatusCode(), std::make_optional(ClusterStatusCode(Status::InvalidCommand))); +} + +TEST_F(TestDynamicLightingCluster, InvokeUnsupportedCommand) +{ + constexpr CommandId kUnsupportedCommandId = 0xFFF0; + + MockCommandHandler handler; + DataModel::InvokeRequest request({ kRootEndpointId, DynamicLighting::Id, kUnsupportedCommandId }, + handler.GetSubjectDescriptor()); + + uint8_t buffer[16]; + TLV::TLVWriter writer; + writer.Init(buffer); + + TLV::TLVType outerContainerType; + ASSERT_EQ(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outerContainerType), CHIP_NO_ERROR); + ASSERT_EQ(writer.EndContainer(outerContainerType), CHIP_NO_ERROR); + ASSERT_EQ(writer.Finalize(), CHIP_NO_ERROR); + + TLV::TLVReader reader; + reader.Init(buffer, writer.GetLengthWritten()); + ASSERT_EQ(reader.Next(TLV::kTLVType_Structure, TLV::AnonymousTag()), CHIP_NO_ERROR); + + EXPECT_EQ(cluster.InvokeCommand(request, reader, &handler), Protocols::InteractionModel::Status::UnsupportedCommand); +} + +TEST_F(TestDynamicLightingCluster, InvokeStopEffectWithNoRunningEffect) +{ + ClusterTester tester(cluster); + + Commands::StopEffect::Type request; + + auto result = tester.Invoke(request); + EXPECT_EQ(result.GetStatusCode(), std::make_optional(ClusterStatusCode(Status::InvalidCommand))); +} diff --git a/src/app/common/templates/config-data.yaml b/src/app/common/templates/config-data.yaml index 75e6cdb733aa61..ac7ab030b3bc14 100644 --- a/src/app/common/templates/config-data.yaml +++ b/src/app/common/templates/config-data.yaml @@ -118,6 +118,7 @@ CodeDrivenClusters: - Device Energy Management Mode - Diagnostic Logs - Dishwasher Mode + - Dynamic Lighting - Electrical Power Measurement - Energy EVSE - Energy EVSE Mode diff --git a/src/app/zap-templates/zcl/zcl-with-test-extensions.json b/src/app/zap-templates/zcl/zcl-with-test-extensions.json index accb6eed42046e..3c60189638acc4 100644 --- a/src/app/zap-templates/zcl/zcl-with-test-extensions.json +++ b/src/app/zap-templates/zcl/zcl-with-test-extensions.json @@ -230,6 +230,12 @@ ], "Binding": ["FeatureMap", "ClusterRevision"], "Chime": ["SelectedChime", "Enabled"], + "Dynamic Lighting": [ + "ClusterRevision", + "FeatureMap", + "CurrentEffectID", + "CurrentSpeed" + ], "Commissioner Control": [ "SupportedDeviceCategories", "FeatureMap", diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json index 5eae36281d28f5..d7692760be5c24 100644 --- a/src/app/zap-templates/zcl/zcl.json +++ b/src/app/zap-templates/zcl/zcl.json @@ -229,6 +229,12 @@ ], "Binding": ["FeatureMap", "ClusterRevision"], "Chime": ["SelectedChime", "Enabled"], + "Dynamic Lighting": [ + "ClusterRevision", + "FeatureMap", + "CurrentEffectID", + "CurrentSpeed" + ], "Commissioner Control": [ "SupportedDeviceCategories", "FeatureMap", diff --git a/src/app/zap_cluster_list.json b/src/app/zap_cluster_list.json index 7d95f0baaa61e4..7857a4bd5d9e63 100644 --- a/src/app/zap_cluster_list.json +++ b/src/app/zap_cluster_list.json @@ -45,6 +45,7 @@ "DIAGNOSTIC_LOGS_CLUSTER": [], "DISHWASHER_ALARM_CLUSTER": [], "DISHWASHER_MODE_CLUSTER": [], + "DYNAMIC_LIGHTING_CLUSTER": [], "ELECTRICAL_ALARM_CLUSTER": [], "ELECTRICAL_DISTRIBUTION_CLUSTER": [], "ELECTRICAL_GRID_CONDITIONS_CLUSTER": [], @@ -226,6 +227,7 @@ "DIAGNOSTIC_LOGS_CLUSTER": ["diagnostic-logs-server"], "DISHWASHER_ALARM_CLUSTER": ["dishwasher-alarm-server"], "DISHWASHER_MODE_CLUSTER": ["mode-base-server"], + "DYNAMIC_LIGHTING_CLUSTER": ["dynamic-lighting-server"], "ELECTRICAL_ALARM_CLUSTER": [], "ELECTRICAL_DISTRIBUTION_CLUSTER": [], "ELECTRICAL_GRID_CONDITIONS_CLUSTER": [ diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp index 9173ed27cdb84f..f4ed1a7b8c2232 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp @@ -23656,283 +23656,7 @@ Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value) } // namespace BallastConfiguration namespace DynamicLighting { -namespace Attributes { - -namespace CurrentEffectID { - -Protocols::InteractionModel::Status Get(EndpointId endpoint, DataModel::Nullable & value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::DynamicLighting::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (Traits::IsNullValue(temp)) - { - value.SetNull(); - } - else - { - value.SetNonNull() = Traits::StorageToWorking(temp); - } - return status; -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ true, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::DynamicLighting::Id, Id), - EmberAfWriteDataInput(writable, ZCL_INT16U_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ true, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::DynamicLighting::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE); -} - -Protocols::InteractionModel::Status SetNull(EndpointId endpoint, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType value; - Traits::SetNull(value); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(value); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::DynamicLighting::Id, Id), - EmberAfWriteDataInput(writable, ZCL_INT16U_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status SetNull(EndpointId endpoint) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType value; - Traits::SetNull(value); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(value); - return emberAfWriteAttribute(endpoint, Clusters::DynamicLighting::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, const chip::app::DataModel::Nullable & value, - MarkAttributeDirty markDirty) -{ - if (value.IsNull()) - { - return SetNull(endpoint, markDirty); - } - - return Set(endpoint, value.Value(), markDirty); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, const chip::app::DataModel::Nullable & value) -{ - if (value.IsNull()) - { - return SetNull(endpoint); - } - - return Set(endpoint, value.Value()); -} - -} // namespace CurrentEffectID - -namespace CurrentSpeed { - -Protocols::InteractionModel::Status Get(EndpointId endpoint, DataModel::Nullable & value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::DynamicLighting::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (Traits::IsNullValue(temp)) - { - value.SetNull(); - } - else - { - value.SetNonNull() = Traits::StorageToWorking(temp); - } - return status; -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ true, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::DynamicLighting::Id, Id), - EmberAfWriteDataInput(writable, ZCL_INT16U_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ true, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::DynamicLighting::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE); -} - -Protocols::InteractionModel::Status SetNull(EndpointId endpoint, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType value; - Traits::SetNull(value); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(value); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::DynamicLighting::Id, Id), - EmberAfWriteDataInput(writable, ZCL_INT16U_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status SetNull(EndpointId endpoint) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType value; - Traits::SetNull(value); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(value); - return emberAfWriteAttribute(endpoint, Clusters::DynamicLighting::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, const chip::app::DataModel::Nullable & value, - MarkAttributeDirty markDirty) -{ - if (value.IsNull()) - { - return SetNull(endpoint, markDirty); - } - - return Set(endpoint, value.Value(), markDirty); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, const chip::app::DataModel::Nullable & value) -{ - if (value.IsNull()) - { - return SetNull(endpoint); - } - - return Set(endpoint, value.Value()); -} - -} // namespace CurrentSpeed - -namespace FeatureMap { - -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint32_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::DynamicLighting::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint32_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::DynamicLighting::Id, Id), - EmberAfWriteDataInput(writable, ZCL_BITMAP32_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint32_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::DynamicLighting::Id, Id, writable, ZCL_BITMAP32_ATTRIBUTE_TYPE); -} - -} // namespace FeatureMap - -namespace ClusterRevision { - -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - Protocols::InteractionModel::Status status = - emberAfReadAttribute(endpoint, Clusters::DynamicLighting::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(Protocols::InteractionModel::Status::Success == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - *value = Traits::StorageToWorking(temp); - return status; -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(ConcreteAttributePath(endpoint, Clusters::DynamicLighting::Id, Id), - EmberAfWriteDataInput(writable, ZCL_INT16U_ATTRIBUTE_TYPE).SetMarkDirty(markDirty)); -} - -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return Protocols::InteractionModel::Status::ConstraintError; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::DynamicLighting::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE); -} - -} // namespace ClusterRevision - -} // namespace Attributes +namespace Attributes {} // namespace Attributes } // namespace DynamicLighting namespace IlluminanceMeasurement { diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h index f311c1ce3cd3d5..8103cce01be128 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h @@ -3886,43 +3886,7 @@ Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value, Mar } // namespace BallastConfiguration namespace DynamicLighting { -namespace Attributes { - -namespace CurrentEffectID { -Protocols::InteractionModel::Status Get(EndpointId endpoint, DataModel::Nullable & value); // int16u -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty); -Protocols::InteractionModel::Status SetNull(EndpointId endpoint); -Protocols::InteractionModel::Status SetNull(EndpointId endpoint, MarkAttributeDirty markDirty); -Protocols::InteractionModel::Status Set(EndpointId endpoint, const chip::app::DataModel::Nullable & value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, const chip::app::DataModel::Nullable & value, - MarkAttributeDirty markDirty); -} // namespace CurrentEffectID - -namespace CurrentSpeed { -Protocols::InteractionModel::Status Get(EndpointId endpoint, DataModel::Nullable & value); // int16u -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty); -Protocols::InteractionModel::Status SetNull(EndpointId endpoint); -Protocols::InteractionModel::Status SetNull(EndpointId endpoint, MarkAttributeDirty markDirty); -Protocols::InteractionModel::Status Set(EndpointId endpoint, const chip::app::DataModel::Nullable & value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, const chip::app::DataModel::Nullable & value, - MarkAttributeDirty markDirty); -} // namespace CurrentSpeed - -namespace FeatureMap { -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint32_t * value); // bitmap32 -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint32_t value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint32_t value, MarkAttributeDirty markDirty); -} // namespace FeatureMap - -namespace ClusterRevision { -Protocols::InteractionModel::Status Get(EndpointId endpoint, uint16_t * value); // int16u -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value); -Protocols::InteractionModel::Status Set(EndpointId endpoint, uint16_t value, MarkAttributeDirty markDirty); -} // namespace ClusterRevision - -} // namespace Attributes +namespace Attributes {} // namespace Attributes } // namespace DynamicLighting namespace IlluminanceMeasurement { diff --git a/zzz_generated/app-common/app-common/zap-generated/callback.h b/zzz_generated/app-common/app-common/zap-generated/callback.h index 326cb0ea973fc0..79af0d3a29aefa 100644 --- a/zzz_generated/app-common/app-common/zap-generated/callback.h +++ b/zzz_generated/app-common/app-common/zap-generated/callback.h @@ -8057,18 +8057,6 @@ bool emberAfColorControlClusterMoveColorTemperatureCallback( bool emberAfColorControlClusterStepColorTemperatureCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::ColorControl::Commands::StepColorTemperature::DecodableType & commandData); -/** - * @brief Dynamic Lighting Cluster StartEffect Command callback (from client) - */ -bool emberAfDynamicLightingClusterStartEffectCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::DynamicLighting::Commands::StartEffect::DecodableType & commandData); -/** - * @brief Dynamic Lighting Cluster StopEffect Command callback (from client) - */ -bool emberAfDynamicLightingClusterStopEffectCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::DynamicLighting::Commands::StopEffect::DecodableType & commandData); /** * @brief Channel Cluster ChangeChannel Command callback (from client) */