From f05b65e8f49835908e802ed1f7c01f5aa8c46087 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Thu, 19 Dec 2024 10:59:03 -0800 Subject: [PATCH] Decouple ember functions from general commissioning cluster (#36836) * Decouple ember functions from general commissioning cluster * Address review comments * Rename gAttrAccess * Remove new added log info * Flag SetTCAcknowledgements command * Revert "Flag SetTCAcknowledgements command" This reverts commit 90de8a12f6b99dfe9419eebbdc95508e52db62d0. * Add the original debug log back --- .../app-templates/IMClusterCommandHandler.cpp | 59 ----- .../app-templates/IMClusterCommandHandler.cpp | 59 ----- .../general-commissioning-server.cpp | 237 ++++++++++-------- src/app/common/templates/config-data.yaml | 1 + .../app-common/zap-generated/callback.h | 24 -- 5 files changed, 130 insertions(+), 250 deletions(-) diff --git a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/IMClusterCommandHandler.cpp b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/IMClusterCommandHandler.cpp index bd3030cf63ddc9..fb772205ed90bd 100644 --- a/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/IMClusterCommandHandler.cpp +++ b/scripts/tools/zap/tests/outputs/all-clusters-app/app-templates/IMClusterCommandHandler.cpp @@ -545,62 +545,6 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } // namespace FaultInjection -namespace GeneralCommissioning { - -void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) -{ - CHIP_ERROR TLVError = CHIP_NO_ERROR; - bool wasHandled = false; - { - switch (aCommandPath.mCommandId) - { - case Commands::ArmFailSafe::Id: { - Commands::ArmFailSafe::DecodableType commandData; - TLVError = DataModel::Decode(aDataTlv, commandData); - if (TLVError == CHIP_NO_ERROR) - { - wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, aCommandPath, commandData); - } - break; - } - case Commands::SetRegulatoryConfig::Id: { - Commands::SetRegulatoryConfig::DecodableType commandData; - TLVError = DataModel::Decode(aDataTlv, commandData); - if (TLVError == CHIP_NO_ERROR) - { - wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback(apCommandObj, aCommandPath, commandData); - } - break; - } - case Commands::CommissioningComplete::Id: { - Commands::CommissioningComplete::DecodableType commandData; - TLVError = DataModel::Decode(aDataTlv, commandData); - if (TLVError == CHIP_NO_ERROR) - { - wasHandled = - emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, commandData); - } - break; - } - default: { - // Unrecognized command ID, error status will apply. - apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); - ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, - ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); - return; - } - } - } - - if (CHIP_NO_ERROR != TLVError || !wasHandled) - { - apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); - } -} - -} // namespace GeneralCommissioning - namespace GeneralDiagnostics { void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) @@ -1958,9 +1902,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: case Clusters::FaultInjection::Id: Clusters::FaultInjection::DispatchServerCommand(apCommandObj, aCommandPath, aReader); break; - case Clusters::GeneralCommissioning::Id: - Clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandPath, aReader); - break; case Clusters::GeneralDiagnostics::Id: Clusters::GeneralDiagnostics::DispatchServerCommand(apCommandObj, aCommandPath, aReader); break; diff --git a/scripts/tools/zap/tests/outputs/lighting-app/app-templates/IMClusterCommandHandler.cpp b/scripts/tools/zap/tests/outputs/lighting-app/app-templates/IMClusterCommandHandler.cpp index aee293138b6ad5..6baabbe22362bf 100644 --- a/scripts/tools/zap/tests/outputs/lighting-app/app-templates/IMClusterCommandHandler.cpp +++ b/scripts/tools/zap/tests/outputs/lighting-app/app-templates/IMClusterCommandHandler.cpp @@ -369,62 +369,6 @@ void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandP } // namespace EthernetNetworkDiagnostics -namespace GeneralCommissioning { - -void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) -{ - CHIP_ERROR TLVError = CHIP_NO_ERROR; - bool wasHandled = false; - { - switch (aCommandPath.mCommandId) - { - case Commands::ArmFailSafe::Id: { - Commands::ArmFailSafe::DecodableType commandData; - TLVError = DataModel::Decode(aDataTlv, commandData); - if (TLVError == CHIP_NO_ERROR) - { - wasHandled = emberAfGeneralCommissioningClusterArmFailSafeCallback(apCommandObj, aCommandPath, commandData); - } - break; - } - case Commands::SetRegulatoryConfig::Id: { - Commands::SetRegulatoryConfig::DecodableType commandData; - TLVError = DataModel::Decode(aDataTlv, commandData); - if (TLVError == CHIP_NO_ERROR) - { - wasHandled = emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback(apCommandObj, aCommandPath, commandData); - } - break; - } - case Commands::CommissioningComplete::Id: { - Commands::CommissioningComplete::DecodableType commandData; - TLVError = DataModel::Decode(aDataTlv, commandData); - if (TLVError == CHIP_NO_ERROR) - { - wasHandled = - emberAfGeneralCommissioningClusterCommissioningCompleteCallback(apCommandObj, aCommandPath, commandData); - } - break; - } - default: { - // Unrecognized command ID, error status will apply. - apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::UnsupportedCommand); - ChipLogError(Zcl, "Unknown command " ChipLogFormatMEI " for cluster " ChipLogFormatMEI, - ChipLogValueMEI(aCommandPath.mCommandId), ChipLogValueMEI(aCommandPath.mClusterId)); - return; - } - } - } - - if (CHIP_NO_ERROR != TLVError || !wasHandled) - { - apCommandObj->AddStatus(aCommandPath, Protocols::InteractionModel::Status::InvalidCommand); - ChipLogProgress(Zcl, "Failed to dispatch command, TLVError=%" CHIP_ERROR_FORMAT, TLVError.Format()); - } -} - -} // namespace GeneralCommissioning - namespace GeneralDiagnostics { void DispatchServerCommand(CommandHandler * apCommandObj, const ConcreteCommandPath & aCommandPath, TLV::TLVReader & aDataTlv) @@ -1115,9 +1059,6 @@ void DispatchSingleClusterCommand(const ConcreteCommandPath & aCommandPath, TLV: case Clusters::EthernetNetworkDiagnostics::Id: Clusters::EthernetNetworkDiagnostics::DispatchServerCommand(apCommandObj, aCommandPath, aReader); break; - case Clusters::GeneralCommissioning::Id: - Clusters::GeneralCommissioning::DispatchServerCommand(apCommandObj, aCommandPath, aReader); - break; case Clusters::GeneralDiagnostics::Id: Clusters::GeneralDiagnostics::DispatchServerCommand(apCommandObj, aCommandPath, aReader); break; diff --git a/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp b/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp index f6fad1d8908243..d47868692a7911 100644 --- a/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp +++ b/src/app/clusters/general-commissioning-server/general-commissioning-server.cpp @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include #include @@ -60,18 +62,21 @@ using Transport::Session; { \ if (!::chip::ChipError::IsSuccess(expr)) \ { \ - commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::code, #expr); \ - return true; \ + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::code, #expr); \ + return; \ } \ } while (false) namespace { -class GeneralCommissioningAttrAccess : public AttributeAccessInterface +class GeneralCommissioningGlobalInstance : public AttributeAccessInterface, public CommandHandlerInterface { public: // Register for the GeneralCommissioning cluster on all endpoints. - GeneralCommissioningAttrAccess() : AttributeAccessInterface(Optional::Missing(), GeneralCommissioning::Id) {} + GeneralCommissioningGlobalInstance() : + AttributeAccessInterface(Optional::Missing(), GeneralCommissioning::Id), + CommandHandlerInterface(Optional::Missing(), GeneralCommissioning::Id) + {} CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; @@ -79,11 +84,20 @@ class GeneralCommissioningAttrAccess : public AttributeAccessInterface CHIP_ERROR ReadIfSupported(CHIP_ERROR (ConfigurationManager::*getter)(uint8_t &), AttributeValueEncoder & aEncoder); CHIP_ERROR ReadBasicCommissioningInfo(AttributeValueEncoder & aEncoder); CHIP_ERROR ReadSupportsConcurrentConnection(AttributeValueEncoder & aEncoder); + + void InvokeCommand(HandlerContext & ctx) override; + + void HandleArmFailSafe(HandlerContext & ctx, const Commands::ArmFailSafe::DecodableType & commandData); + void HandleCommissioningComplete(HandlerContext & ctx, const Commands::CommissioningComplete::DecodableType & commandData); + void HandleSetRegulatoryConfig(HandlerContext & ctx, const Commands::SetRegulatoryConfig::DecodableType & commandData); +#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED + void HandleSetTCAcknowledgements(HandlerContext & ctx, const Commands::SetTCAcknowledgements::DecodableType & commandData); +#endif }; -GeneralCommissioningAttrAccess gAttrAccess; +GeneralCommissioningGlobalInstance gGeneralCommissioningInstance; -CHIP_ERROR GeneralCommissioningAttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) +CHIP_ERROR GeneralCommissioningGlobalInstance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) { if (aPath.mClusterId != GeneralCommissioning::Id) { @@ -164,10 +178,10 @@ CHIP_ERROR GeneralCommissioningAttrAccess::Read(const ConcreteReadAttributePath return CHIP_NO_ERROR; } -CHIP_ERROR GeneralCommissioningAttrAccess::ReadIfSupported(CHIP_ERROR (ConfigurationManager::*getter)(uint8_t &), - AttributeValueEncoder & aEncoder) +CHIP_ERROR GeneralCommissioningGlobalInstance::ReadIfSupported(CHIP_ERROR (ConfigurationManager::*getter)(uint8_t &), + AttributeValueEncoder & aEncoder) { - uint8_t data; + uint8_t data = 0; CHIP_ERROR err = (DeviceLayer::ConfigurationMgr().*getter)(data); if (err == CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE) { @@ -177,25 +191,24 @@ CHIP_ERROR GeneralCommissioningAttrAccess::ReadIfSupported(CHIP_ERROR (Configura { return err; } - return aEncoder.Encode(data); } -CHIP_ERROR GeneralCommissioningAttrAccess::ReadBasicCommissioningInfo(AttributeValueEncoder & aEncoder) +CHIP_ERROR GeneralCommissioningGlobalInstance::ReadBasicCommissioningInfo(AttributeValueEncoder & aEncoder) { - BasicCommissioningInfo::TypeInfo::Type basicCommissioningInfo; + BasicCommissioningInfo::TypeInfo::Type info; // TODO: The commissioner might use the critical parameters in BasicCommissioningInfo to initialize // the CommissioningParameters at the beginning of commissioning flow. - basicCommissioningInfo.failSafeExpiryLengthSeconds = CHIP_DEVICE_CONFIG_FAILSAFE_EXPIRY_LENGTH_SEC; - basicCommissioningInfo.maxCumulativeFailsafeSeconds = CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC; + info.failSafeExpiryLengthSeconds = CHIP_DEVICE_CONFIG_FAILSAFE_EXPIRY_LENGTH_SEC; + info.maxCumulativeFailsafeSeconds = CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC; static_assert(CHIP_DEVICE_CONFIG_MAX_CUMULATIVE_FAILSAFE_SEC >= CHIP_DEVICE_CONFIG_FAILSAFE_EXPIRY_LENGTH_SEC, "Max cumulative failsafe seconds must be larger than failsafe expiry length seconds"); - return aEncoder.Encode(basicCommissioningInfo); + return aEncoder.Encode(info); } -CHIP_ERROR GeneralCommissioningAttrAccess::ReadSupportsConcurrentConnection(AttributeValueEncoder & aEncoder) +CHIP_ERROR GeneralCommissioningGlobalInstance::ReadSupportsConcurrentConnection(AttributeValueEncoder & aEncoder) { SupportsConcurrentConnection::TypeInfo::Type supportsConcurrentConnection; @@ -206,6 +219,37 @@ CHIP_ERROR GeneralCommissioningAttrAccess::ReadSupportsConcurrentConnection(Attr return aEncoder.Encode(supportsConcurrentConnection); } +void GeneralCommissioningGlobalInstance::InvokeCommand(HandlerContext & handlerContext) +{ + switch (handlerContext.mRequestPath.mCommandId) + { + case Commands::ArmFailSafe::Id: + CommandHandlerInterface::HandleCommand( + handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleArmFailSafe(ctx, commandData); }); + break; + + case Commands::CommissioningComplete::Id: + CommandHandlerInterface::HandleCommand( + handlerContext, + [this](HandlerContext & ctx, const auto & commandData) { HandleCommissioningComplete(ctx, commandData); }); + break; + + case Commands::SetRegulatoryConfig::Id: + CommandHandlerInterface::HandleCommand( + handlerContext, + [this](HandlerContext & ctx, const auto & commandData) { HandleSetRegulatoryConfig(ctx, commandData); }); + break; + +#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED + case Commands::SetTCAcknowledgements::Id: + CommandHandlerInterface::HandleCommand( + handlerContext, + [this](HandlerContext & ctx, const auto & commandData) { HandleSetTCAcknowledgements(ctx, commandData); }); + break; +#endif + } +} + #if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED typedef struct sTermsAndConditionsState { @@ -273,10 +317,7 @@ void NotifyTermsAndConditionsAttributeChangeIfRequired(const TermsAndConditionsS } #endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED -} // anonymous namespace - -bool emberAfGeneralCommissioningClusterArmFailSafeCallback(app::CommandHandler * commandObj, - const app::ConcreteCommandPath & commandPath, +void GeneralCommissioningGlobalInstance::HandleArmFailSafe(HandlerContext & ctx, const Commands::ArmFailSafe::DecodableType & commandData) { MATTER_TRACE_SCOPE("ArmFailSafe", "GeneralCommissioning"); @@ -292,8 +333,7 @@ bool emberAfGeneralCommissioningClusterArmFailSafeCallback(app::CommandHandler * * If the fail-safe timer was currently armed, and current accessing fabric matches the fail-safe * context’s Fabric Index, then the fail-safe timer SHALL be re-armed. */ - - FabricIndex accessingFabricIndex = commandObj->GetAccessingFabricIndex(); + FabricIndex accessingFabricIndex = ctx.mCommandHandler.GetAccessingFabricIndex(); // We do not allow CASE connections to arm the failsafe for the first time while the commissioning window is open in order // to allow commissioners the opportunity to obtain this failsafe for the purpose of commissioning @@ -304,10 +344,9 @@ bool emberAfGeneralCommissioningClusterArmFailSafeCallback(app::CommandHandler * // to allow commissioners the opportunity to obtain this failsafe for the purpose of commissioning if (!failSafeContext.IsFailSafeArmed() && Server::GetInstance().GetCommissioningWindowManager().IsCommissioningWindowOpen() && - commandObj->GetSubjectDescriptor().authMode == Access::AuthMode::kCase) + ctx.mCommandHandler.GetSubjectDescriptor().authMode == Access::AuthMode::kCase) { response.errorCode = CommissioningErrorEnum::kBusyWithOtherAdmin; - commandObj->AddResponse(commandPath, response); } else if (commandData.expiryLengthSeconds == 0) { @@ -316,30 +355,26 @@ bool emberAfGeneralCommissioningClusterArmFailSafeCallback(app::CommandHandler * // Don't set the breadcrumb, since expiring the failsafe should // reset it anyway. response.errorCode = CommissioningErrorEnum::kOk; - commandObj->AddResponse(commandPath, response); } else { CheckSuccess( failSafeContext.ArmFailSafe(accessingFabricIndex, System::Clock::Seconds16(commandData.expiryLengthSeconds)), Failure); - Breadcrumb::Set(commandPath.mEndpointId, commandData.breadcrumb); + Breadcrumb::Set(ctx.mRequestPath.mEndpointId, commandData.breadcrumb); response.errorCode = CommissioningErrorEnum::kOk; - commandObj->AddResponse(commandPath, response); } } else { response.errorCode = CommissioningErrorEnum::kBusyWithOtherAdmin; - commandObj->AddResponse(commandPath, response); } - return true; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); } -bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback( - app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, - const Commands::CommissioningComplete::DecodableType & commandData) +void GeneralCommissioningGlobalInstance::HandleCommissioningComplete( + HandlerContext & ctx, const Commands::CommissioningComplete::DecodableType & commandData) { MATTER_TRACE_SCOPE("CommissioningComplete", "GeneralCommissioning"); @@ -347,8 +382,6 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback( auto & failSafe = Server::GetInstance().GetFailSafeContext(); auto & fabricTable = Server::GetInstance().GetFabricTable(); - CHIP_ERROR err = CHIP_NO_ERROR; - ChipLogProgress(FailSafe, "GeneralCommissioning: Received CommissioningComplete"); Commands::CommissioningCompleteResponse::Type response; @@ -357,8 +390,8 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback( if (!failSafe.IsFailSafeArmed()) { response.errorCode = CommissioningErrorEnum::kNoFailSafe; - commandObj->AddResponse(commandPath, response); - return true; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; } #if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED @@ -376,8 +409,8 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback( if (requiredTermsAndConditionsMaybe.HasValue() && !acceptedTermsAndConditionsMaybe.HasValue()) { response.errorCode = CommissioningErrorEnum::kTCAcknowledgementsNotReceived; - commandObj->AddResponse(commandPath, response); - return true; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; } if (requiredTermsAndConditionsMaybe.HasValue() && acceptedTermsAndConditionsMaybe.HasValue()) @@ -388,15 +421,15 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback( if (!requiredTermsAndConditions.ValidateVersion(acceptedTermsAndConditions)) { response.errorCode = CommissioningErrorEnum::kTCMinVersionNotMet; - commandObj->AddResponse(commandPath, response); - return true; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; } if (!requiredTermsAndConditions.ValidateValue(acceptedTermsAndConditions)) { response.errorCode = CommissioningErrorEnum::kRequiredTCNotAccepted; - commandObj->AddResponse(commandPath, response); - return true; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; } } @@ -418,17 +451,18 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback( } #endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED - SessionHandle handle = commandObj->GetExchangeContext()->GetSessionHandle(); + SessionHandle handle = ctx.mCommandHandler.GetExchangeContext()->GetSessionHandle(); + CHIP_ERROR err = CHIP_NO_ERROR; // Ensure it's a valid CASE session - if ((handle->GetSessionType() != Session::SessionType::kSecure) || - (handle->AsSecureSession()->GetSecureSessionType() != SecureSession::Type::kCASE) || - (!failSafe.MatchesFabricIndex(commandObj->GetAccessingFabricIndex()))) + if (handle->GetSessionType() != Session::SessionType::kSecure || + handle->AsSecureSession()->GetSecureSessionType() != SecureSession::Type::kCASE || + !failSafe.MatchesFabricIndex(ctx.mCommandHandler.GetAccessingFabricIndex())) { response.errorCode = CommissioningErrorEnum::kInvalidAuthentication; ChipLogError(FailSafe, "GeneralCommissioning: Got commissioning complete in invalid security context"); - commandObj->AddResponse(commandPath, response); - return true; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; } // Handle NOC commands @@ -452,80 +486,70 @@ bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback( err = devCtrl->PostCommissioningCompleteEvent(handle->AsSecureSession()->GetPeerNodeId(), handle->GetFabricIndex()); CheckSuccess(err, Failure); - Breadcrumb::Set(commandPath.mEndpointId, 0); + Breadcrumb::Set(ctx.mRequestPath.mEndpointId, 0); response.errorCode = CommissioningErrorEnum::kOk; - - commandObj->AddResponse(commandPath, response); - return true; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); } -bool emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback(app::CommandHandler * commandObj, - const app::ConcreteCommandPath & commandPath, +void GeneralCommissioningGlobalInstance::HandleSetRegulatoryConfig(HandlerContext & ctx, const Commands::SetRegulatoryConfig::DecodableType & commandData) { MATTER_TRACE_SCOPE("SetRegulatoryConfig", "GeneralCommissioning"); DeviceControlServer * server = &DeviceLayer::DeviceControlServer::DeviceControlSvr(); Commands::SetRegulatoryConfigResponse::Type response; - auto & countryCode = commandData.countryCode; - bool isValidLength = countryCode.size() == DeviceLayer::ConfigurationManager::kMaxLocationLength; - if (!isValidLength) + + if (countryCode.size() != ConfigurationManager::kMaxLocationLength) { ChipLogError(Zcl, "Invalid country code: '%.*s'", static_cast(countryCode.size()), countryCode.data()); - commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::ConstraintError); - return true; + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::ConstraintError); + return; } if (commandData.newRegulatoryConfig > RegulatoryLocationTypeEnum::kIndoorOutdoor) { response.errorCode = CommissioningErrorEnum::kValueOutsideRange; - // TODO: How does using the country code in debug text make sense, if - // the real issue is the newRegulatoryConfig value? - response.debugText = countryCode; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; } - else + + uint8_t locationCapability; + if (ConfigurationMgr().GetLocationCapability(locationCapability) != CHIP_NO_ERROR) { - uint8_t locationCapability; - uint8_t location = to_underlying(commandData.newRegulatoryConfig); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::Failure); + return; + } - CheckSuccess(ConfigurationMgr().GetLocationCapability(locationCapability), Failure); + uint8_t location = to_underlying(commandData.newRegulatoryConfig); - // If the LocationCapability attribute is not Indoor/Outdoor and the NewRegulatoryConfig value received does not match - // either the Indoor or Outdoor fixed value in LocationCapability. - if ((locationCapability != to_underlying(RegulatoryLocationTypeEnum::kIndoorOutdoor)) && (location != locationCapability)) - { - response.errorCode = CommissioningErrorEnum::kValueOutsideRange; - // TODO: How does using the country code in debug text make sense, if - // the real issue is the newRegulatoryConfig value? - response.debugText = countryCode; - } - else - { - CheckSuccess(server->SetRegulatoryConfig(location, countryCode), Failure); - Breadcrumb::Set(commandPath.mEndpointId, commandData.breadcrumb); - response.errorCode = CommissioningErrorEnum::kOk; - } + // If the LocationCapability attribute is not Indoor/Outdoor and the NewRegulatoryConfig value received does not match + // either the Indoor or Outdoor fixed value in LocationCapability. + if ((locationCapability != to_underlying(RegulatoryLocationTypeEnum::kIndoorOutdoor)) && (location != locationCapability)) + { + response.errorCode = CommissioningErrorEnum::kValueOutsideRange; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; } - commandObj->AddResponse(commandPath, response); - - return true; + CheckSuccess(server->SetRegulatoryConfig(location, countryCode), Failure); + Breadcrumb::Set(ctx.mRequestPath.mEndpointId, commandData.breadcrumb); + response.errorCode = CommissioningErrorEnum::kOk; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); } -bool emberAfGeneralCommissioningClusterSetTCAcknowledgementsCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const GeneralCommissioning::Commands::SetTCAcknowledgements::DecodableType & commandData) +#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED +void GeneralCommissioningGlobalInstance::HandleSetTCAcknowledgements( + HandlerContext & ctx, const Commands::SetTCAcknowledgements::DecodableType & commandData) { MATTER_TRACE_SCOPE("SetTCAcknowledgements", "GeneralCommissioning"); -#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED auto & failSafeContext = Server::GetInstance().GetFailSafeContext(); TermsAndConditionsProvider * tcProvider = TermsAndConditionsManager::GetInstance(); if (nullptr == tcProvider) { - commandObj->AddStatus(commandPath, Protocols::InteractionModel::Status::Failure); - return true; + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Protocols::InteractionModel::Status::Failure); + return; } Optional requiredTermsAndConditionsMaybe; @@ -544,15 +568,15 @@ bool emberAfGeneralCommissioningClusterSetTCAcknowledgementsCallback( if (!requiredTermsAndConditions.ValidateVersion(acceptedTermsAndConditions)) { response.errorCode = CommissioningErrorEnum::kTCMinVersionNotMet; - commandObj->AddResponse(commandPath, response); - return true; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; } if (!requiredTermsAndConditions.ValidateValue(acceptedTermsAndConditions)) { response.errorCode = CommissioningErrorEnum::kRequiredTCNotAccepted; - commandObj->AddResponse(commandPath, response); - return true; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); + return; } } @@ -576,24 +600,20 @@ bool emberAfGeneralCommissioningClusterSetTCAcknowledgementsCallback( } response.errorCode = CommissioningErrorEnum::kOk; - commandObj->AddResponse(commandPath, response); - return true; - -#endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED - return true; + ctx.mCommandHandler.AddResponse(ctx.mRequestPath, response); } +#endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED -namespace { -void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t arg) +void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t) { if (event->Type == DeviceLayer::DeviceEventType::kFailSafeTimerExpired) { // Spec says to reset Breadcrumb attribute to 0. Breadcrumb::Set(0, 0); +#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED if (event->FailSafeTimerExpired.updateTermsAndConditionsHasBeenInvoked) { -#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED // Clear terms and conditions acceptance on failsafe timer expiration TermsAndConditionsProvider * tcProvider = TermsAndConditionsManager::GetInstance(); TermsAndConditionsState initialState, updatedState; @@ -602,8 +622,8 @@ void OnPlatformEventHandler(const DeviceLayer::ChipDeviceEvent * event, intptr_t VerifyOrReturn(CHIP_NO_ERROR == tcProvider->RevertAcceptance()); VerifyOrReturn(CHIP_NO_ERROR == GetTermsAndConditionsAttributeState(tcProvider, updatedState)); NotifyTermsAndConditionsAttributeChangeIfRequired(initialState, updatedState); -#endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED } +#endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED } } @@ -615,6 +635,7 @@ class GeneralCommissioningFabricTableDelegate : public chip::FabricTable::Delega // Gets called when a fabric is deleted void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override { +#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED // If the FabricIndex matches the last remaining entry in the Fabrics list, then the device SHALL delete all Matter // related data on the node which was created since it was commissioned. if (Server::GetInstance().GetFabricTable().FabricCount() == 0) @@ -622,7 +643,6 @@ class GeneralCommissioningFabricTableDelegate : public chip::FabricTable::Delega ChipLogProgress(Zcl, "general-commissioning-server: Last Fabric index 0x%x was removed", static_cast(fabricIndex)); -#if CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED TermsAndConditionsProvider * tcProvider = TermsAndConditionsManager::GetInstance(); TermsAndConditionsState initialState, updatedState; VerifyOrReturn(nullptr != tcProvider); @@ -630,19 +650,20 @@ class GeneralCommissioningFabricTableDelegate : public chip::FabricTable::Delega VerifyOrReturn(CHIP_NO_ERROR == tcProvider->ResetAcceptance()); VerifyOrReturn(CHIP_NO_ERROR == GetTermsAndConditionsAttributeState(tcProvider, updatedState)); NotifyTermsAndConditionsAttributeChangeIfRequired(initialState, updatedState); -#endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED } +#endif // CHIP_CONFIG_TERMS_AND_CONDITIONS_REQUIRED } }; void MatterGeneralCommissioningPluginServerInitCallback() { Breadcrumb::Set(0, 0); - AttributeAccessInterfaceRegistry::Instance().Register(&gAttrAccess); + AttributeAccessInterfaceRegistry::Instance().Register(&gGeneralCommissioningInstance); + ReturnOnFailure(CommandHandlerInterfaceRegistry::Instance().RegisterCommandHandler(&gGeneralCommissioningInstance)); DeviceLayer::PlatformMgrImpl().AddEventHandler(OnPlatformEventHandler); - static GeneralCommissioningFabricTableDelegate generalCommissioningFabricTableDelegate; - Server::GetInstance().GetFabricTable().AddFabricDelegate(&generalCommissioningFabricTableDelegate); + static GeneralCommissioningFabricTableDelegate fabricDelegate; + Server::GetInstance().GetFabricTable().AddFabricDelegate(&fabricDelegate); } namespace chip { diff --git a/src/app/common/templates/config-data.yaml b/src/app/common/templates/config-data.yaml index b014f103e96fda..c6bff2b65788c9 100644 --- a/src/app/common/templates/config-data.yaml +++ b/src/app/common/templates/config-data.yaml @@ -49,6 +49,7 @@ CommandHandlerInterfaceOnlyClusters: - Thread Network Directory - Water Heater Management - Water Heater Mode + - General Commissioning # We need a more configurable way of deciding which clusters have which init functions.... # See https://github.com/project-chip/connectedhomeip/issues/4369 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 b594c4cce72675..8360f83add3c33 100644 --- a/zzz_generated/app-common/app-common/zap-generated/callback.h +++ b/zzz_generated/app-common/app-common/zap-generated/callback.h @@ -5822,30 +5822,6 @@ bool emberAfOtaSoftwareUpdateProviderClusterNotifyUpdateAppliedCallback( bool emberAfOtaSoftwareUpdateRequestorClusterAnnounceOTAProviderCallback( chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, const chip::app::Clusters::OtaSoftwareUpdateRequestor::Commands::AnnounceOTAProvider::DecodableType & commandData); -/** - * @brief General Commissioning Cluster ArmFailSafe Command callback (from client) - */ -bool emberAfGeneralCommissioningClusterArmFailSafeCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::GeneralCommissioning::Commands::ArmFailSafe::DecodableType & commandData); -/** - * @brief General Commissioning Cluster SetRegulatoryConfig Command callback (from client) - */ -bool emberAfGeneralCommissioningClusterSetRegulatoryConfigCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::GeneralCommissioning::Commands::SetRegulatoryConfig::DecodableType & commandData); -/** - * @brief General Commissioning Cluster CommissioningComplete Command callback (from client) - */ -bool emberAfGeneralCommissioningClusterCommissioningCompleteCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::GeneralCommissioning::Commands::CommissioningComplete::DecodableType & commandData); -/** - * @brief General Commissioning Cluster SetTCAcknowledgements Command callback (from client) - */ -bool emberAfGeneralCommissioningClusterSetTCAcknowledgementsCallback( - chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::GeneralCommissioning::Commands::SetTCAcknowledgements::DecodableType & commandData); /** * @brief Diagnostic Logs Cluster RetrieveLogsRequest Command callback (from client) */