diff --git a/docs/upgrading.md b/docs/upgrading.md index e9e17239d50049..8e77cc3afe38ba 100644 --- a/docs/upgrading.md +++ b/docs/upgrading.md @@ -107,3 +107,87 @@ To use default attribute persistence, you need to pass in a `PersistentStorageDelegate` to `CodegenDataModelProviderInstance`. See example changes in [36658](https://github.com/project-chip/connectedhomeip/pull/36658) ). + +### Decoupling of Command Handler Interface from Ember + +#### EnumerateGeneratedCommands + +Changed the old callback based iteration, into a ListBuilder based approach for +the Enumeration of Generated Commands + +`CommandHandlerInterface::EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context)` +becomes +`CommandHandlerInterface::EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, ListBuilder & builder)` + +Changes for implementation + +- old + +```cpp + for (auto && cmd : { ScanNetworksResponse::Id, NetworkConfigResponse::Id, ConnectNetworkResponse::Id }) + { + VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/); + } +``` + +- new + +```cpp + ReturnErrorOnFailure( + builder.AppendElements({ ScanNetworksResponse::Id, NetworkConfigResponse::Id, ConnectNetworkResponse::Id }) + ) +``` + +#### EnumerateAcceptedCommands + +Expanded `EnumerateAcceptedCommands` Interface to provide the Access Information +(Attributes and Qualities) using a ListBuilder + +`CommandHandlerInterface::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context)` +becomes +`CommandHandlerInterface::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, ListBuilder & builder)` + +Changes for implementation: + +- Old + +```cpp + for (auto && cmd : { + Disable::Id, + EnableCharging::Id, + }) + { + VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/); + } + + if (HasFeature(Feature::kV2x)) + { + VerifyOrExit(callback(EnableDischarging::Id, context) == Loop::Continue, /**/); + } +``` + +- new + +```cpp + using QF = DataModel::CommandQualityFlags; + using Priv = Access::Privilege; + + ReturnErrorOnFailure(builder.AppendElements({ + { Disable::Id, QF::kTimed, Priv::kOperate }, + { EnableCharging::Id, QF::kTimed, Priv::kOperate }, + })); + + if (HasFeature(Feature::kV2x)) + { + ReturnErrorOnFailure(builder.EnsureAppendCapacity(1)); + ReturnErrorOnFailure( + builder.Append({ EnableDischarging::Id, QF::kTimed, Priv::kOperate}) + ); + } + +``` + +Important Notes: + +Use `EnsureAppendCapacity` before `ListBuilder::Append` to prevent buffer +overflow when appending a single element, this function never allocates. diff --git a/src/app/CommandHandlerInterface.h b/src/app/CommandHandlerInterface.h index 4146556779756c..47cedcc5c8cfdf 100644 --- a/src/app/CommandHandlerInterface.h +++ b/src/app/CommandHandlerInterface.h @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include // So we can encode lists #include @@ -28,7 +30,6 @@ namespace chip { namespace app { - /* * This interface permits applications to register a server-side command handler * at run-time for a given cluster. The handler can either be configured to handle all endpoints @@ -122,7 +123,8 @@ class CommandHandlerInterface * This is used by callbacks that just look for a particular value in the * list. */ - virtual CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) + virtual CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, + DataModel::ListBuilder & builder) { return CHIP_ERROR_NOT_IMPLEMENTED; } @@ -146,7 +148,7 @@ class CommandHandlerInterface * This is used by callbacks that just look for a particular value in the * list. */ - virtual CHIP_ERROR EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) + virtual CHIP_ERROR EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, DataModel::ListBuilder & builder) { return CHIP_ERROR_NOT_IMPLEMENTED; } diff --git a/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp b/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp index 0b7205dd83a33a..8791a842676711 100644 --- a/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp +++ b/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp @@ -104,49 +104,51 @@ CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValu } // CommandHandlerInterface -CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) +CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, + DataModel::ListBuilder & builder) { using namespace Commands; + using Priv = Access::Privilege; + + ReturnErrorOnFailure(builder.EnsureAppendCapacity(8)); // Ensure we have capacity for all possible commands if (HasFeature(Feature::kPowerAdjustment)) { - for (auto && cmd : { - PowerAdjustRequest::Id, - CancelPowerAdjustRequest::Id, - }) - { - VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/); - } + ReturnErrorOnFailure(builder.AppendElements({ + { PowerAdjustRequest::Id, {}, Priv::kOperate }, // + { CancelPowerAdjustRequest::Id, {}, Priv::kOperate } // + })); } if (HasFeature(Feature::kStartTimeAdjustment)) { - VerifyOrExit(callback(StartTimeAdjustRequest::Id, context) == Loop::Continue, /**/); + ReturnErrorOnFailure(builder.Append({ StartTimeAdjustRequest::Id, {}, Priv::kOperate })); } if (HasFeature(Feature::kPausable)) { - VerifyOrExit(callback(PauseRequest::Id, context) == Loop::Continue, /**/); - VerifyOrExit(callback(ResumeRequest::Id, context) == Loop::Continue, /**/); + ReturnErrorOnFailure(builder.AppendElements({ + { PauseRequest::Id, {}, Priv::kOperate }, // + { ResumeRequest::Id, {}, Priv::kOperate } // + })); } if (HasFeature(Feature::kForecastAdjustment)) { - VerifyOrExit(callback(ModifyForecastRequest::Id, context) == Loop::Continue, /**/); + ReturnErrorOnFailure(builder.Append({ ModifyForecastRequest::Id, {}, Priv::kOperate })); } if (HasFeature(Feature::kConstraintBasedAdjustment)) { - VerifyOrExit(callback(RequestConstraintBasedForecast::Id, context) == Loop::Continue, /**/); + ReturnErrorOnFailure(builder.Append({ RequestConstraintBasedForecast::Id, {}, Priv::kOperate })); } if (HasFeature(Feature::kStartTimeAdjustment) || HasFeature(Feature::kForecastAdjustment) || HasFeature(Feature::kConstraintBasedAdjustment)) { - VerifyOrExit(callback(CancelRequest::Id, context) == Loop::Continue, /**/); + ReturnErrorOnFailure(builder.Append({ CancelRequest::Id, {}, Priv::kOperate })); } -exit: return CHIP_NO_ERROR; } diff --git a/src/app/clusters/device-energy-management-server/device-energy-management-server.h b/src/app/clusters/device-energy-management-server/device-energy-management-server.h index c58e5c5a73743a..069f1c1b1965e4 100644 --- a/src/app/clusters/device-energy-management-server/device-energy-management-server.h +++ b/src/app/clusters/device-energy-management-server/device-energy-management-server.h @@ -235,7 +235,8 @@ class Instance : public AttributeAccessInterface, public CommandHandlerInterface // CommandHandlerInterface void InvokeCommand(HandlerContext & handlerContext) override; - CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override; + CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, + DataModel::ListBuilder & builder) override; Protocols::InteractionModel::Status CheckOptOutAllowsRequest(AdjustmentCauseEnum adjustmentCause); void HandlePowerAdjustRequest(HandlerContext & ctx, const Commands::PowerAdjustRequest::DecodableType & commandData); diff --git a/src/app/clusters/energy-evse-server/energy-evse-server.cpp b/src/app/clusters/energy-evse-server/energy-evse-server.cpp index d4ae59307cfea1..a598bf7428da4c 100644 --- a/src/app/clusters/energy-evse-server/energy-evse-server.cpp +++ b/src/app/clusters/energy-evse-server/energy-evse-server.cpp @@ -182,41 +182,37 @@ CHIP_ERROR Instance::Write(const ConcreteDataAttributePath & aPath, AttributeVal } // CommandHandlerInterface -CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) +CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, + DataModel::ListBuilder & builder) { using namespace Commands; + using QF = DataModel::CommandQualityFlags; + using Priv = Access::Privilege; + ReturnErrorOnFailure(builder.EnsureAppendCapacity(7)); - for (auto && cmd : { - Disable::Id, - EnableCharging::Id, - }) - { - VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/); - } + ReturnErrorOnFailure(builder.AppendElements({ + { Disable::Id, QF::kTimed, Priv::kOperate }, // + { EnableCharging::Id, QF::kTimed, Priv::kOperate }, // + })); if (HasFeature(Feature::kV2x)) { - VerifyOrExit(callback(EnableDischarging::Id, context) == Loop::Continue, /**/); + ReturnErrorOnFailure(builder.Append({ EnableDischarging::Id, QF::kTimed, Priv::kOperate })); } if (HasFeature(Feature::kChargingPreferences)) { - for (auto && cmd : { - SetTargets::Id, - GetTargets::Id, - ClearTargets::Id, - }) - { - VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/); - } + ReturnErrorOnFailure(builder.AppendElements({ + { SetTargets::Id, QF::kTimed, Priv::kOperate }, // + { GetTargets::Id, QF::kTimed, Priv::kOperate }, // + { ClearTargets::Id, QF::kTimed, Priv::kOperate }, // + })); } if (SupportsOptCmd(OptionalCommands::kSupportsStartDiagnostics)) { - callback(StartDiagnostics::Id, context); + ReturnErrorOnFailure(builder.Append({ StartDiagnostics::Id, QF::kTimed, Priv::kOperate })); } - -exit: return CHIP_NO_ERROR; } diff --git a/src/app/clusters/energy-evse-server/energy-evse-server.h b/src/app/clusters/energy-evse-server/energy-evse-server.h index 979e44c040a17b..6031eb8ac76a5a 100644 --- a/src/app/clusters/energy-evse-server/energy-evse-server.h +++ b/src/app/clusters/energy-evse-server/energy-evse-server.h @@ -200,7 +200,8 @@ class Instance : public AttributeAccessInterface, public CommandHandlerInterface // CommandHandlerInterface void InvokeCommand(HandlerContext & handlerContext) override; - CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override; + CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, + DataModel::ListBuilder & builder) override; void HandleDisable(HandlerContext & ctx, const Commands::Disable::DecodableType & commandData); void HandleEnableCharging(HandlerContext & ctx, const Commands::EnableCharging::DecodableType & commandData); diff --git a/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp b/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp index 5d823d0cafe3cb..1fa83ffbf43ac2 100644 --- a/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp +++ b/src/app/clusters/microwave-oven-control-server/microwave-oven-control-server.cpp @@ -16,7 +16,6 @@ * */ -#include "app/data-model-provider/MetadataList.h" #include #include #include @@ -24,6 +23,7 @@ #include #include #include +#include #include #include #include diff --git a/src/app/clusters/network-commissioning/network-commissioning.cpp b/src/app/clusters/network-commissioning/network-commissioning.cpp index ea73b8ff23d9eb..4fa6d541b4709b 100644 --- a/src/app/clusters/network-commissioning/network-commissioning.cpp +++ b/src/app/clusters/network-commissioning/network-commissioning.cpp @@ -1360,64 +1360,56 @@ void Instance::OnFailSafeTimerExpired() } } -CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) +CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, + DataModel::ListBuilder & builder) { using namespace Clusters::NetworkCommissioning::Commands; + using Priv = Access::Privilege; - if (mFeatureFlags.Has(Feature::kThreadNetworkInterface)) - { - for (auto && cmd : { - ScanNetworks::Id, - AddOrUpdateThreadNetwork::Id, - RemoveNetwork::Id, - ConnectNetwork::Id, - ReorderNetwork::Id, - }) - { - VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/); - } - } - else if (mFeatureFlags.Has(Feature::kWiFiNetworkInterface)) + static constexpr size_t kNetworkCommands = 7; // Count of max possible commands assuming all features + ReturnErrorOnFailure(builder.EnsureAppendCapacity(kNetworkCommands)); + + bool hasThread = mFeatureFlags.Has(Feature::kThreadNetworkInterface); + bool hasWifi = mFeatureFlags.Has(Feature::kWiFiNetworkInterface); + + if (hasThread || hasWifi) { - for (auto && cmd : { - ScanNetworks::Id, - AddOrUpdateWiFiNetwork::Id, - RemoveNetwork::Id, - ConnectNetwork::Id, - ReorderNetwork::Id, - }) - { - VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/); - } + ReturnErrorOnFailure(builder.AppendElements({ + { ScanNetworks::Id, {}, Priv::kAdminister }, // + { RemoveNetwork::Id, {}, Priv::kAdminister }, // + { ConnectNetwork::Id, {}, Priv::kAdminister }, // + { ReorderNetwork::Id, {}, Priv::kAdminister }, // + })); + ReturnErrorOnFailure( + builder.Append({ hasThread ? AddOrUpdateThreadNetwork::Id : AddOrUpdateWiFiNetwork::Id, {}, Priv::kAdminister })); } if (mFeatureFlags.Has(Feature::kPerDeviceCredentials)) { - VerifyOrExit(callback(QueryIdentity::Id, context) == Loop::Continue, /**/); + ReturnErrorOnFailure(builder.Append({ QueryIdentity::Id, {}, Priv::kAdminister })); } -exit: return CHIP_NO_ERROR; } -CHIP_ERROR Instance::EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) +CHIP_ERROR Instance::EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, DataModel::ListBuilder & builder) { using namespace Clusters::NetworkCommissioning::Commands; + static constexpr size_t kCommands = 4; // Count of max possible commands assuming all features + ReturnErrorOnFailure(builder.EnsureAppendCapacity(kCommands)); + if (mFeatureFlags.HasAny(Feature::kWiFiNetworkInterface, Feature::kThreadNetworkInterface)) { - for (auto && cmd : { ScanNetworksResponse::Id, NetworkConfigResponse::Id, ConnectNetworkResponse::Id }) - { - VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/); - } + ReturnErrorOnFailure( + builder.AppendElements({ ScanNetworksResponse::Id, NetworkConfigResponse::Id, ConnectNetworkResponse::Id })); } if (mFeatureFlags.Has(Feature::kPerDeviceCredentials)) { - VerifyOrExit(callback(QueryIdentityResponse::Id, context) == Loop::Continue, /**/); + ReturnErrorOnFailure(builder.Append(QueryIdentityResponse::Id)); } -exit: return CHIP_NO_ERROR; } diff --git a/src/app/clusters/network-commissioning/network-commissioning.h b/src/app/clusters/network-commissioning/network-commissioning.h index d727c9b6c2beb9..a3c82bb79105f8 100644 --- a/src/app/clusters/network-commissioning/network-commissioning.h +++ b/src/app/clusters/network-commissioning/network-commissioning.h @@ -59,8 +59,10 @@ class Instance : public CommandHandlerInterface, // CommandHandlerInterface void InvokeCommand(HandlerContext & ctx) override; - CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override; - CHIP_ERROR EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override; + CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, + DataModel::ListBuilder & builder) override; + CHIP_ERROR EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, + DataModel::ListBuilder & builder) override; // AttributeAccessInterface CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; diff --git a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp index 6c581ff72a9e19..6fe79a538fc748 100644 --- a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp +++ b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.cpp @@ -188,12 +188,16 @@ void Instance::InvokeCommand(HandlerContext & handlerContext) // List the commands supported by this instance. CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, - CommandHandlerInterface::CommandIdCallback callback, void * context) + DataModel::ListBuilder & builder) { + using namespace ResourceMonitoring::Commands; + using Priv = Access::Privilege; + ChipLogDetail(Zcl, "resourcemonitoring: EnumerateAcceptedCommands"); if (mResetConditionCommandSupported) { - callback(ResourceMonitoring::Commands::ResetCondition::Id, context); + ReturnErrorOnFailure(builder.EnsureAppendCapacity(1)); + return builder.Append({ ResetCondition::Id, {}, Priv::kOperate }); } return CHIP_NO_ERROR; diff --git a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.h b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.h index 45c96c39f30074..a43fa4262d2329 100644 --- a/src/app/clusters/resource-monitoring-server/resource-monitoring-server.h +++ b/src/app/clusters/resource-monitoring-server/resource-monitoring-server.h @@ -132,7 +132,8 @@ class Instance : public CommandHandlerInterface, public AttributeAccessInterface // CommandHandlerInterface void InvokeCommand(HandlerContext & ctx) override; - CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override; + CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, + DataModel::ListBuilder & builder) override; // AttributeAccessInterface CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; diff --git a/src/app/clusters/software-diagnostics-server/software-diagnostics-server.cpp b/src/app/clusters/software-diagnostics-server/software-diagnostics-server.cpp index 6d78a13d4f6560..9dbcc1af4e0163 100644 --- a/src/app/clusters/software-diagnostics-server/software-diagnostics-server.cpp +++ b/src/app/clusters/software-diagnostics-server/software-diagnostics-server.cpp @@ -62,7 +62,8 @@ class SoftwareDiagnosticsCommandHandler : public CommandHandlerInterface void InvokeCommand(HandlerContext & handlerContext) override; - CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override; + CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, + DataModel::ListBuilder & builder) override; }; SoftwareDiagnosticsAttrAccess gAttrAccess; @@ -168,18 +169,19 @@ void SoftwareDiagnosticsCommandHandler::InvokeCommand(HandlerContext & handlerCo handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, status); } -CHIP_ERROR SoftwareDiagnosticsCommandHandler::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, - CommandIdCallback callback, void * context) +CHIP_ERROR +SoftwareDiagnosticsCommandHandler::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, + DataModel::ListBuilder & builder) { + using namespace Commands; + using Priv = Access::Privilege; if (!DeviceLayer::GetDiagnosticDataProvider().SupportsWatermarks()) { // No commmands. return CHIP_NO_ERROR; } - - callback(Commands::ResetWatermarks::Id, context); - - return CHIP_NO_ERROR; + ReturnErrorOnFailure(builder.EnsureAppendCapacity(1)); + return builder.Append({ ResetWatermarks::Id, {}, Priv::kManage }); } } // anonymous namespace diff --git a/src/app/data-model-provider/MetadataList.h b/src/app/data-model-provider/MetadataList.h index 24a34c8223f655..569459a929a39a 100644 --- a/src/app/data-model-provider/MetadataList.h +++ b/src/app/data-model-provider/MetadataList.h @@ -178,6 +178,12 @@ class ListBuilder : public detail::GenericAppendOnlyBuffer /// via `Take`) CHIP_ERROR AppendElements(SpanType span) { return AppendElementArrayRaw(span.data(), span.size()); } + /// Append always attempts to append/extend existing memory. + /// + /// Automatically attempts to allocate sufficient space to fulfill the element + /// requirements. + CHIP_ERROR AppendElements(std::initializer_list span) { return AppendElementArrayRaw(span.begin(), span.size()); } + /// Append a single element. /// Sufficent append capacity MUST exist. CHIP_ERROR Append(const T & value) { return AppendSingleElementRaw(&value); } diff --git a/src/controller/tests/TestServerCommandDispatch.cpp b/src/controller/tests/TestServerCommandDispatch.cpp index 17acaa5887c14b..f7f739203aef33 100644 --- a/src/controller/tests/TestServerCommandDispatch.cpp +++ b/src/controller/tests/TestServerCommandDispatch.cpp @@ -69,7 +69,8 @@ class TestClusterCommandHandler : public chip::app::CommandHandlerInterface private: void InvokeCommand(chip::app::CommandHandlerInterface::HandlerContext & handlerContext) final; - CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) final; + CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, + DataModel::ListBuilder & builder) final; bool mOverrideAcceptedCommands = false; bool mClaimNoCommands = false; @@ -105,8 +106,11 @@ void TestClusterCommandHandler::InvokeCommand(chip::app::CommandHandlerInterface } CHIP_ERROR TestClusterCommandHandler::EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, - CommandHandlerInterface::CommandIdCallback callback, void * context) + DataModel::ListBuilder & builder) { + using namespace Clusters::UnitTesting::Commands; + using Priv = Access::Privilege; + if (!mOverrideAcceptedCommands) { return CHIP_ERROR_NOT_IMPLEMENTED; @@ -117,9 +121,8 @@ CHIP_ERROR TestClusterCommandHandler::EnumerateAcceptedCommands(const ConcreteCl return CHIP_NO_ERROR; } - // We just have one command id. - callback(Clusters::UnitTesting::Commands::TestSimpleArgumentRequest::Id, context); - return CHIP_NO_ERROR; + static constexpr DataModel::AcceptedCommandEntry entries[] = { { TestSimpleArgumentRequest::Id, {}, Priv::kOperate } }; + return builder.ReferenceExisting({ entries, std::size(entries) }); } } // namespace diff --git a/src/data-model-providers/codegen/CodegenDataModelProvider.cpp b/src/data-model-providers/codegen/CodegenDataModelProvider.cpp index 6913214ac803cc..2e8b51807695c1 100644 --- a/src/data-model-providers/codegen/CodegenDataModelProvider.cpp +++ b/src/data-model-providers/codegen/CodegenDataModelProvider.cpp @@ -361,52 +361,9 @@ CHIP_ERROR CodegenDataModelProvider::AcceptedCommands(const ConcreteClusterPath CommandHandlerInterfaceRegistry::Instance().GetCommandHandler(path.mEndpointId, path.mClusterId); if (interface != nullptr) { - size_t commandCount = 0; - - CHIP_ERROR err = interface->EnumerateAcceptedCommands( - path, - [](CommandId id, void * context) -> Loop { - *reinterpret_cast(context) += 1; - return Loop::Continue; - }, - reinterpret_cast(&commandCount)); - - if (err == CHIP_NO_ERROR) - { - using EnumerationData = struct - { - ConcreteCommandPath commandPath; - DataModel::ListBuilder * acceptedCommandList; - CHIP_ERROR processingError; - }; - - EnumerationData enumerationData; - enumerationData.commandPath = ConcreteCommandPath(path.mEndpointId, path.mClusterId, kInvalidCommandId); - enumerationData.processingError = CHIP_NO_ERROR; - enumerationData.acceptedCommandList = &builder; - - ReturnErrorOnFailure(builder.EnsureAppendCapacity(commandCount)); - - ReturnErrorOnFailure(interface->EnumerateAcceptedCommands( - path, - [](CommandId commandId, void * context) -> Loop { - auto input = reinterpret_cast(context); - input->commandPath.mCommandId = commandId; - CHIP_ERROR appendError = input->acceptedCommandList->Append(AcceptedCommandEntryFor(input->commandPath)); - if (appendError != CHIP_NO_ERROR) - { - input->processingError = appendError; - return Loop::Break; - } - return Loop::Continue; - }, - reinterpret_cast(&enumerationData))); - ReturnErrorOnFailure(enumerationData.processingError); - - // the two invocations MUST return the same sizes. - VerifyOrReturnError(builder.Size() == commandCount, CHIP_ERROR_INTERNAL); - return CHIP_NO_ERROR; - } + CHIP_ERROR err = interface->EnumerateAcceptedCommands(path, builder); + // if enumeration returns CHIP_ERROR_NOT_IMPLEMENTED then continue with normal procesing + // otherwise we finished VerifyOrReturnError(err == CHIP_ERROR_NOT_IMPLEMENTED, err); } @@ -445,49 +402,9 @@ CHIP_ERROR CodegenDataModelProvider::GeneratedCommands(const ConcreteClusterPath CommandHandlerInterfaceRegistry::Instance().GetCommandHandler(path.mEndpointId, path.mClusterId); if (interface != nullptr) { - size_t commandCount = 0; - - CHIP_ERROR err = interface->EnumerateGeneratedCommands( - path, - [](CommandId id, void * context) -> Loop { - *reinterpret_cast(context) += 1; - return Loop::Continue; - }, - reinterpret_cast(&commandCount)); - - if (err == CHIP_NO_ERROR) - { - ReturnErrorOnFailure(builder.EnsureAppendCapacity(commandCount)); - - using EnumerationData = struct - { - DataModel::ListBuilder * generatedCommandList; - CHIP_ERROR processingError; - }; - EnumerationData enumerationData; - enumerationData.processingError = CHIP_NO_ERROR; - enumerationData.generatedCommandList = &builder; - - ReturnErrorOnFailure(interface->EnumerateGeneratedCommands( - path, - [](CommandId id, void * context) -> Loop { - auto input = reinterpret_cast(context); - - CHIP_ERROR appendError = input->generatedCommandList->Append(id); - if (appendError != CHIP_NO_ERROR) - { - input->processingError = appendError; - return Loop::Break; - } - return Loop::Continue; - }, - reinterpret_cast(&enumerationData))); - ReturnErrorOnFailure(enumerationData.processingError); - - // the two invocations MUST return the same sizes. - VerifyOrReturnError(builder.Size() == commandCount, CHIP_ERROR_INTERNAL); - return CHIP_NO_ERROR; - } + CHIP_ERROR err = interface->EnumerateGeneratedCommands(path, builder); + // If enumeration returns CHIP_ERROR_NOT_IMPLEMENTED then continue with normal procesing + // otherwise we finished VerifyOrReturnError(err == CHIP_ERROR_NOT_IMPLEMENTED, err); } diff --git a/src/data-model-providers/codegen/tests/TestCodegenModelViaMocks.cpp b/src/data-model-providers/codegen/tests/TestCodegenModelViaMocks.cpp index bcd9d64d88d86d..ad503fcb9b2860 100644 --- a/src/data-model-providers/codegen/tests/TestCodegenModelViaMocks.cpp +++ b/src/data-model-providers/codegen/tests/TestCodegenModelViaMocks.cpp @@ -282,38 +282,22 @@ class CustomListCommandHandler : public CommandHandlerInterface void SetHandleCommands(bool handle) { mHandleCommand = handle; } - CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override + CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, + DataModel::ListBuilder & builder) override { - VerifyOrReturnError(mOverrideAccepted, CHIP_ERROR_NOT_IMPLEMENTED); - - for (auto id : mAccepted) - { - if (callback(id, context) != Loop::Continue) - { - break; - } - } - return CHIP_NO_ERROR; + return builder.ReferenceExisting({ mAccepted.data(), mAccepted.size() }); } - CHIP_ERROR EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override + CHIP_ERROR EnumerateGeneratedCommands(const ConcreteClusterPath & cluster, DataModel::ListBuilder & builder) override { VerifyOrReturnError(mOverrideGenerated, CHIP_ERROR_NOT_IMPLEMENTED); - - for (auto id : mGenerated) - { - if (callback(id, context) != Loop::Continue) - { - break; - } - } - return CHIP_NO_ERROR; + return builder.AppendElements({ mGenerated.data(), mGenerated.size() }); } void SetOverrideAccepted(bool o) { mOverrideAccepted = o; } void SetOverrideGenerated(bool o) { mOverrideGenerated = o; } - std::vector & AcceptedVec() { return mAccepted; } + std::vector & AcceptedVec() { return mAccepted; } std::vector & GeneratedVec() { return mGenerated; } private: @@ -321,7 +305,7 @@ class CustomListCommandHandler : public CommandHandlerInterface bool mOverrideGenerated = false; bool mHandleCommand = false; - std::vector mAccepted; + std::vector mAccepted; std::vector mGenerated; }; @@ -1283,8 +1267,8 @@ TEST_F(TestCodegenModelViaMocks, CommandHandlerInterfaceCommandHandling) ASSERT_TRUE(acceptedBuilder.IsEmpty()); // set some overrides - handler.AcceptedVec().push_back(1234); - handler.AcceptedVec().push_back(999); + handler.AcceptedVec().push_back({ 1234, {} }); + handler.AcceptedVec().push_back({ 999, {} }); handler.GeneratedVec().push_back(33);