From 89afc6107b6ebde596b0b8e435087d190b08dd48 Mon Sep 17 00:00:00 2001 From: Ricardo Casallas Date: Wed, 19 Jul 2023 10:38:19 -0400 Subject: [PATCH] ICD: Publisher-selected maximum subscription interval. --- .../all-clusters-app.matter | 10 +- .../data_model/lighting-thread-app.matter | 10 +- .../smoke-co-alarm-app.matter | 10 +- src/app/BUILD.gn | 1 + src/app/ReadHandler.cpp | 13 ++ src/app/ReadHandler.h | 11 +- src/app/chip_data_model.cmake | 1 + src/app/chip_data_model.gni | 2 +- .../icd-management-server.cpp | 193 +++++++----------- .../icd-management-server.h | 20 -- src/app/icd/BUILD.gn | 9 +- src/app/icd/ICDManager.cpp | 25 +-- src/app/icd/IcdManagementServer.cpp | 81 ++++++++ src/app/icd/IcdManagementServer.h | 76 +++++++ src/app/icd/IcdMonitoringTable.cpp | 46 ++++- src/app/icd/IcdMonitoringTable.h | 10 +- src/app/tests/BUILD.gn | 2 +- .../zcl/zcl-with-test-extensions.json | 8 + src/app/zap-templates/zcl/zcl.json | 8 + src/lib/core/CHIPConfig.h | 36 ++++ .../zap-generated/attributes/Accessors.cpp | 155 -------------- .../zap-generated/attributes/Accessors.h | 25 --- 22 files changed, 389 insertions(+), 363 deletions(-) create mode 100644 src/app/icd/IcdManagementServer.cpp create mode 100644 src/app/icd/IcdManagementServer.h 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 b7688606b70c62..ae43361517c1c6 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 @@ -6489,12 +6489,12 @@ endpoint 0 { } server cluster IcdManagement { - ram attribute idleModeInterval default = 500; - ram attribute activeModeInterval default = 300; - ram attribute activeModeThreshold default = 300; + callback attribute idleModeInterval default = 500; + callback attribute activeModeInterval default = 300; + callback attribute activeModeThreshold default = 300; callback attribute registeredClients; - ram attribute ICDCounter default = 0; - ram attribute clientsSupportedPerFabric default = 2; + callback attribute ICDCounter default = 0; + callback attribute clientsSupportedPerFabric default = 2; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; diff --git a/examples/lighting-app/silabs/data_model/lighting-thread-app.matter b/examples/lighting-app/silabs/data_model/lighting-thread-app.matter index a7040b2bee6001..de8055dd495f05 100644 --- a/examples/lighting-app/silabs/data_model/lighting-thread-app.matter +++ b/examples/lighting-app/silabs/data_model/lighting-thread-app.matter @@ -2474,12 +2474,12 @@ endpoint 0 { } server cluster IcdManagement { - ram attribute idleModeInterval default = 500; - ram attribute activeModeInterval default = 300; - ram attribute activeModeThreshold default = 300; + callback attribute idleModeInterval default = 500; + callback attribute activeModeInterval default = 300; + callback attribute activeModeThreshold default = 300; callback attribute registeredClients; - ram attribute ICDCounter; - ram attribute clientsSupportedPerFabric default = 1; + callback attribute ICDCounter; + callback attribute clientsSupportedPerFabric default = 1; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; diff --git a/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter b/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter index f48b0979eff509..26db9451812a0f 100644 --- a/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter +++ b/examples/smoke-co-alarm-app/smoke-co-alarm-common/smoke-co-alarm-app.matter @@ -2166,12 +2166,12 @@ endpoint 0 { } server cluster IcdManagement { - ram attribute idleModeInterval default = 500; - ram attribute activeModeInterval default = 300; - ram attribute activeModeThreshold default = 300; + callback attribute idleModeInterval default = 500; + callback attribute activeModeInterval default = 300; + callback attribute activeModeThreshold default = 300; callback attribute registeredClients; - ram attribute ICDCounter; - ram attribute clientsSupportedPerFabric default = 1; + callback attribute ICDCounter; + callback attribute clientsSupportedPerFabric default = 1; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index 7f2c4d82280392..487c43e3182a5b 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -209,6 +209,7 @@ static_library("app") { public_deps = [ ":app_config", "${chip_root}/src/access", + "${chip_root}/src/app/icd:cluster-srcs", "${chip_root}/src/lib/address_resolve", "${chip_root}/src/lib/support", "${chip_root}/src/messaging", diff --git a/src/app/ReadHandler.cpp b/src/app/ReadHandler.cpp index a5209ae45d588e..1328559a85ac64 100644 --- a/src/app/ReadHandler.cpp +++ b/src/app/ReadHandler.cpp @@ -34,10 +34,23 @@ #include #include +#if CHIP_CONFIG_ENABLE_ICD_SERVER +#include // nogncheck +#endif + namespace chip { namespace app { using Status = Protocols::InteractionModel::Status; +uint16_t ReadHandler::GetPublisherSelectedIntervalLimit() +{ +#if CHIP_CONFIG_ENABLE_ICD_SERVER + return static_cast(IcdManagementServer::GetInstance().GetIdleModeInterval() / 1000); +#else + return kSubscriptionMaxIntervalPublisherLimit; +#endif +} + ReadHandler::ReadHandler(ManagementCallback & apCallback, Messaging::ExchangeContext * apExchangeContext, InteractionType aInteractionType, Observer * observer) : mExchangeCtx(*this), diff --git a/src/app/ReadHandler.h b/src/app/ReadHandler.h index 77c88c12cd1ff9..5b9bb346eb7894 100644 --- a/src/app/ReadHandler.h +++ b/src/app/ReadHandler.h @@ -52,7 +52,7 @@ #include // https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/61a9d19e6af12fdfb0872bcff26d19de6c680a1a/src/Ch02_Architecture.adoc#1122-subscribe-interaction-limits -constexpr uint16_t kSubscriptionMaxIntervalPublisherLimit = 3600; // 3600 seconds +constexpr uint16_t kSubscriptionMaxIntervalPublisherLimit = 3600; // seconds (60 minutes) namespace chip { namespace app { @@ -244,7 +244,7 @@ class ReadHandler : public Messaging::ExchangeDelegate { VerifyOrReturnError(IsIdle(), CHIP_ERROR_INCORRECT_STATE); VerifyOrReturnError(mMinIntervalFloorSeconds <= aMaxInterval, CHIP_ERROR_INVALID_ARGUMENT); - VerifyOrReturnError(aMaxInterval <= std::max(kSubscriptionMaxIntervalPublisherLimit, mMaxInterval), + VerifyOrReturnError(aMaxInterval <= std::max(GetPublisherSelectedIntervalLimit(), mMaxInterval), CHIP_ERROR_INVALID_ARGUMENT); mMaxInterval = aMaxInterval; return CHIP_NO_ERROR; @@ -266,6 +266,13 @@ class ReadHandler : public Messaging::ExchangeDelegate PriorityLevel GetCurrentPriority() const { return mCurrentPriority; } EventNumber & GetEventMin() { return mEventMin; } + /** + * Returns SUBSCRIPTION_MAX_INTERVAL_PUBLISHER_LIMIT + * For an ICD publisher, this SHALL be set to the idle mode interval. + * Otherwise, this SHALL be set to 60 minutes. + */ + uint16_t GetPublisherSelectedIntervalLimit(); + enum class ReadHandlerFlags : uint8_t { // WaitingUntilMinInterval is used to prevent subscription data delivery while we are diff --git a/src/app/chip_data_model.cmake b/src/app/chip_data_model.cmake index 5033b0373be684..8f0f7f82301cfc 100644 --- a/src/app/chip_data_model.cmake +++ b/src/app/chip_data_model.cmake @@ -144,6 +144,7 @@ function(chip_configure_data_model APP_TARGET) ${CHIP_APP_BASE_DIR}/util/attribute-table.cpp ${CHIP_APP_BASE_DIR}/util/binding-table.cpp ${CHIP_APP_BASE_DIR}/icd/IcdMonitoringTable.cpp + ${CHIP_APP_BASE_DIR}/icd/IcdManagementServer.cpp ${CHIP_APP_BASE_DIR}/util/DataModelHandler.cpp ${CHIP_APP_BASE_DIR}/util/ember-compatibility-functions.cpp ${CHIP_APP_BASE_DIR}/util/error-mapping.cpp diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index 7092359888812c..05777aaec5f0c1 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -266,7 +266,7 @@ template("chip_data_model") { } else if (cluster == "icd-management-server") { sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp" ] - deps += [ "${chip_root}/src/app/icd:monitoring-table" ] + deps += [ "${chip_root}/src/app/icd:cluster-srcs" ] } else { sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp" ] } diff --git a/src/app/clusters/icd-management-server/icd-management-server.cpp b/src/app/clusters/icd-management-server/icd-management-server.cpp index 93378de2880d6b..30fc0b072c7448 100644 --- a/src/app/clusters/icd-management-server/icd-management-server.cpp +++ b/src/app/clusters/icd-management-server/icd-management-server.cpp @@ -17,7 +17,6 @@ #include "icd-management-server.h" -#include "app/server/Server.h" #include #include #include @@ -26,7 +25,9 @@ #include #include #include +#include #include +#include #include #include @@ -50,7 +51,12 @@ class IcdManagementAttributeAccess : public app::AttributeAccessInterface CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; private: + CHIP_ERROR ReadIdleModeInterval(EndpointId endpoint, AttributeValueEncoder & encoder); + CHIP_ERROR ReadActiveModeInterval(EndpointId endpoint, AttributeValueEncoder & encoder); + CHIP_ERROR ReadActiveModeThreshold(EndpointId endpoint, AttributeValueEncoder & encoder); CHIP_ERROR ReadRegisteredClients(EndpointId endpoint, AttributeValueEncoder & encoder); + CHIP_ERROR ReadICDCounter(EndpointId endpoint, AttributeValueEncoder & encoder); + CHIP_ERROR ReadClientsSupportedPerFabric(EndpointId endpoint, AttributeValueEncoder & encoder); }; CHIP_ERROR IcdManagementAttributeAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) @@ -59,21 +65,46 @@ CHIP_ERROR IcdManagementAttributeAccess::Read(const ConcreteReadAttributePath & switch (aPath.mAttributeId) { + case IcdManagement::Attributes::IdleModeInterval::Id: + return ReadIdleModeInterval(aPath.mEndpointId, aEncoder); + + case IcdManagement::Attributes::ActiveModeInterval::Id: + return ReadActiveModeInterval(aPath.mEndpointId, aEncoder); + + case IcdManagement::Attributes::ActiveModeThreshold::Id: + return ReadActiveModeThreshold(aPath.mEndpointId, aEncoder); + case IcdManagement::Attributes::RegisteredClients::Id: return ReadRegisteredClients(aPath.mEndpointId, aEncoder); - default: - break; + case IcdManagement::Attributes::ICDCounter::Id: + return ReadICDCounter(aPath.mEndpointId, aEncoder); + + case IcdManagement::Attributes::ClientsSupportedPerFabric::Id: + return ReadClientsSupportedPerFabric(aPath.mEndpointId, aEncoder); } return CHIP_NO_ERROR; } +CHIP_ERROR IcdManagementAttributeAccess::ReadIdleModeInterval(EndpointId endpoint, AttributeValueEncoder & encoder) +{ + return encoder.Encode(IcdManagementServer::GetInstance().GetIdleModeInterval()); +} + +CHIP_ERROR IcdManagementAttributeAccess::ReadActiveModeInterval(EndpointId endpoint, AttributeValueEncoder & encoder) +{ + return encoder.Encode(IcdManagementServer::GetInstance().GetActiveModeInterval()); +} + +CHIP_ERROR IcdManagementAttributeAccess::ReadActiveModeThreshold(EndpointId endpoint, AttributeValueEncoder & encoder) +{ + return encoder.Encode(IcdManagementServer::GetInstance().GetActiveModeThreshold()); +} + CHIP_ERROR IcdManagementAttributeAccess::ReadRegisteredClients(EndpointId endpoint, AttributeValueEncoder & encoder) { - uint16_t supported_clients = 0; - VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == Attributes::ClientsSupportedPerFabric::Get(endpoint, &supported_clients), - CHIP_ERROR_NOT_FOUND); + uint16_t supported_clients = IcdManagementServer::GetInstance().GetClientsSupportedPerFabric(); return encoder.EncodeList([supported_clients](const auto & subEncoder) -> CHIP_ERROR { IcdMonitoringEntry e; @@ -92,13 +123,28 @@ CHIP_ERROR IcdManagementAttributeAccess::ReadRegisteredClients(EndpointId endpoi break; } ReturnErrorOnFailure(err); - ReturnErrorOnFailure(subEncoder.Encode(e)); + + Structs::MonitoringRegistrationStruct::Type s{ .checkInNodeID = e.checkInNodeID, + .monitoredSubject = e.monitoredSubject, + .key = e.key, + .fabricIndex = e.fabricIndex }; + ReturnErrorOnFailure(subEncoder.Encode(s)); } } return CHIP_NO_ERROR; }); } +CHIP_ERROR IcdManagementAttributeAccess::ReadICDCounter(EndpointId endpoint, AttributeValueEncoder & encoder) +{ + return encoder.Encode(IcdManagementServer::GetInstance().GetICDCounter()); +} + +CHIP_ERROR IcdManagementAttributeAccess::ReadClientsSupportedPerFabric(EndpointId endpoint, AttributeValueEncoder & encoder) +{ + return encoder.Encode(IcdManagementServer::GetInstance().GetClientsSupportedPerFabric()); +} + CHIP_ERROR CheckAdmin(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, bool & is_admin) { RequestPath requestPath{ .cluster = commandPath.mClusterId, .endpoint = commandPath.mEndpointId }; @@ -119,12 +165,7 @@ class IcdManagementFabricDelegate : public chip::FabricTable::Delegate { void OnFabricRemoved(const FabricTable & fabricTable, FabricIndex fabricIndex) override { - uint16_t supported_clients = 0; - if (EMBER_ZCL_STATUS_SUCCESS != Attributes::ClientsSupportedPerFabric::Get(kRootEndpointId, &supported_clients)) - { - // Fallback to maximum, the remove function will loop until no more entries are found. - supported_clients = UINT16_MAX; - } + uint16_t supported_clients = IcdManagementServer::GetInstance().GetClientsSupportedPerFabric(); IcdMonitoringTable table(chip::Server::GetInstance().GetPersistentStorage(), fabricIndex, supported_clients); table.RemoveAll(); } @@ -135,95 +176,6 @@ IcdManagementAttributeAccess gAttribute; } // namespace -InteractionModel::Status IcdManagementServer::RegisterClient(chip::app::CommandHandler * commandObj, - const chip::app::ConcreteCommandPath & commandPath, - const Commands::RegisterClient::DecodableType & commandData) -{ - uint16_t supported_clients = 0; - VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == - Attributes::ClientsSupportedPerFabric::Get(commandPath.mEndpointId, &supported_clients), - InteractionModel::Status::Failure); - IcdMonitoringTable table(chip::Server::GetInstance().GetPersistentStorage(), commandObj->GetAccessingFabricIndex(), - supported_clients); - - // Get current entry, if exists - IcdMonitoringEntry entry; - CHIP_ERROR err = table.Find(commandData.checkInNodeID, entry); - if (CHIP_NO_ERROR == err) - { - // Existing entry: Validate Key if, and only if, the ISD has NOT administrator permissions - bool is_admin = false; - err = CheckAdmin(commandObj, commandPath, is_admin); - VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); - if (!is_admin) - { - VerifyOrReturnError(commandData.verificationKey.HasValue(), InteractionModel::Status::Failure); - VerifyOrReturnError(commandData.verificationKey.Value().data_equal(entry.key), InteractionModel::Status::Failure); - } - } - else if (CHIP_ERROR_NOT_FOUND == err) - { - // New entry - VerifyOrReturnError(entry.index < table.Limit(), InteractionModel::Status::ResourceExhausted); - } - else - { - // Error - return InteractionModel::Status::Failure; - } - - // Save - entry.checkInNodeID = commandData.checkInNodeID; - entry.monitoredSubject = commandData.monitoredSubject; - entry.key = commandData.key; - err = table.Set(entry.index, entry); - VerifyOrReturnError(CHIP_ERROR_INVALID_ARGUMENT != err, InteractionModel::Status::ConstraintError); - VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); - - return InteractionModel::Status::Success; -} - -InteractionModel::Status IcdManagementServer::UnregisterClient(chip::app::CommandHandler * commandObj, - const chip::app::ConcreteCommandPath & commandPath, - const Commands::UnregisterClient::DecodableType & commandData) -{ - uint16_t supported_clients = 0; - VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == - Attributes::ClientsSupportedPerFabric::Get(commandPath.mEndpointId, &supported_clients), - InteractionModel::Status::Failure); - IcdMonitoringTable table(chip::Server::GetInstance().GetPersistentStorage(), commandObj->GetAccessingFabricIndex(), - supported_clients); - - // Get current entry, if exists - IcdMonitoringEntry entry; - CHIP_ERROR err = table.Find(commandData.checkInNodeID, entry); - VerifyOrReturnError(CHIP_ERROR_NOT_FOUND != err, InteractionModel::Status::NotFound); - VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); - - // Existing entry: Validate Key if, and only if, the ISD has NOT administrator permissions - bool is_admin = false; - err = CheckAdmin(commandObj, commandPath, is_admin); - VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); - - if (!is_admin) - { - VerifyOrReturnError(commandData.key.HasValue(), InteractionModel::Status::Failure); - VerifyOrReturnError(commandData.key.Value().data_equal(entry.key), InteractionModel::Status::Failure); - } - - err = table.Remove(entry.index); - VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); - - return InteractionModel::Status::Success; -} - -InteractionModel::Status IcdManagementServer::StayActiveRequest(const chip::app::ConcreteCommandPath & commandPath) -{ - - // TODO: Implementent stay awake logic for end device - return InteractionModel::Status::UnsupportedCommand; -} - void emberAfIcdManagementClusterInitCallback() { Server::GetInstance().GetFabricTable().AddFabricDelegate(&gFabricDelegate); @@ -237,19 +189,24 @@ bool emberAfIcdManagementClusterRegisterClientCallback(chip::app::CommandHandler const chip::app::ConcreteCommandPath & commandPath, const Commands::RegisterClient::DecodableType & commandData) { - IcdManagementServer server; + InteractionModel::Status status = InteractionModel::Status::Failure; + bool is_admin = false; + if (CHIP_NO_ERROR == CheckAdmin(commandObj, commandPath, is_admin)) + { + PersistentStorageDelegate & storage = chip::Server::GetInstance().GetPersistentStorage(); + FabricIndex fabric = commandObj->GetAccessingFabricIndex(); + status = IcdManagementServer::GetInstance().RegisterClient(storage, fabric, commandData.checkInNodeID, + commandData.monitoredSubject, commandData.key, + commandData.verificationKey, is_admin); + } - InteractionModel::Status status = server.RegisterClient(commandObj, commandPath, commandData); if (InteractionModel::Status::Success == status) { // Response - IcdManagement::Commands::RegisterClientResponse::Type response; - if (EMBER_ZCL_STATUS_SUCCESS == Attributes::ICDCounter::Get(commandPath.mEndpointId, &response.ICDCounter)) - { - commandObj->AddResponse(commandPath, response); - return true; - } - status = InteractionModel::Status::Failure; + IcdManagement::Commands::RegisterClientResponse::Type response{ .ICDCounter = + IcdManagementServer::GetInstance().GetICDCounter() }; + commandObj->AddResponse(commandPath, response); + return true; } // Error @@ -265,8 +222,15 @@ bool emberAfIcdManagementClusterUnregisterClientCallback(chip::app::CommandHandl const chip::app::ConcreteCommandPath & commandPath, const Commands::UnregisterClient::DecodableType & commandData) { - IcdManagementServer server; - InteractionModel::Status status = server.UnregisterClient(commandObj, commandPath, commandData); + InteractionModel::Status status = InteractionModel::Status::Failure; + bool is_admin = false; + if (CHIP_NO_ERROR == CheckAdmin(commandObj, commandPath, is_admin)) + { + PersistentStorageDelegate & storage = chip::Server::GetInstance().GetPersistentStorage(); + FabricIndex fabric = commandObj->GetAccessingFabricIndex(); + status = IcdManagementServer::GetInstance().UnregisterClient(storage, fabric, commandData.checkInNodeID, commandData.key, + is_admin); + } commandObj->AddStatus(commandPath, status); return true; @@ -279,8 +243,7 @@ bool emberAfIcdManagementClusterStayActiveRequestCallback(chip::app::CommandHand const chip::app::ConcreteCommandPath & commandPath, const Commands::StayActiveRequest::DecodableType & commandData) { - IcdManagementServer server; - InteractionModel::Status status = server.StayActiveRequest(commandPath); + InteractionModel::Status status = IcdManagementServer::GetInstance().StayActiveRequest(commandObj->GetAccessingFabricIndex()); commandObj->AddStatus(commandPath, status); return true; diff --git a/src/app/clusters/icd-management-server/icd-management-server.h b/src/app/clusters/icd-management-server/icd-management-server.h index 1534ac86543d87..69c11082f14c02 100644 --- a/src/app/clusters/icd-management-server/icd-management-server.h +++ b/src/app/clusters/icd-management-server/icd-management-server.h @@ -16,23 +16,3 @@ */ #pragma once - -#include -#include -#include -#include -#include - -using chip::Protocols::InteractionModel::Status; - -class IcdManagementServer -{ -public: - Status RegisterClient(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::IcdManagement::Commands::RegisterClient::DecodableType & commandData); - - Status UnregisterClient(chip::app::CommandHandler * commandObj, const chip::app::ConcreteCommandPath & commandPath, - const chip::app::Clusters::IcdManagement::Commands::UnregisterClient::DecodableType & commandData); - - Status StayActiveRequest(const chip::app::ConcreteCommandPath & commandPath); -}; diff --git a/src/app/icd/BUILD.gn b/src/app/icd/BUILD.gn index a6bd21299bc9e5..f4d5b9a7375dac 100644 --- a/src/app/icd/BUILD.gn +++ b/src/app/icd/BUILD.gn @@ -25,12 +25,16 @@ source_set("manager-srcs") { "ICDManager.h", ] - deps = [ ":monitoring-table" ] + deps = [ ":cluster-srcs" ] public_deps = [ "${chip_root}/src/credentials:credentials" ] } -source_set("monitoring-table") { +# ICD management cluster source-set is broken out of the main source-set to enable unit tests +# All sources and configurations used by the ICD management cluster need to go in this source-set +source_set("cluster-srcs") { sources = [ + "IcdManagementServer.cpp", + "IcdManagementServer.h", "IcdMonitoringTable.cpp", "IcdMonitoringTable.h", ] @@ -38,6 +42,7 @@ source_set("monitoring-table") { public_deps = [ "${chip_root}/src/lib/core", "${chip_root}/src/platform:platform", + "${chip_root}/src/protocols:im_status", ] } diff --git a/src/app/icd/ICDManager.cpp b/src/app/icd/ICDManager.cpp index dffb4e0227b76a..6ab66b2e252975 100644 --- a/src/app/icd/ICDManager.cpp +++ b/src/app/icd/ICDManager.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -41,11 +42,7 @@ void ICDManager::ICDManager::Init(PersistentStorageDelegate * storage, FabricTab mStorage = storage; mFabricTable = fabricTable; - uint32_t activeModeInterval; - if (Attributes::ActiveModeInterval::Get(kRootEndpointId, &activeModeInterval) != EMBER_ZCL_STATUS_SUCCESS) - { - activeModeInterval = kMinActiveModeInterval; - } + uint32_t activeModeInterval = IcdManagementServer::GetInstance().GetActiveModeInterval(); VerifyOrDie(kFastPollingInterval.count() < activeModeInterval); UpdateIcdMode(); UpdateOperationState(OperationalState::ActiveMode); @@ -106,11 +103,7 @@ void ICDManager::UpdateOperationState(OperationalState state) if (state == OperationalState::IdleMode) { mOperationalState = OperationalState::IdleMode; - uint32_t idleModeInterval = 0; - if (Attributes::IdleModeInterval::Get(kRootEndpointId, &idleModeInterval) != EMBER_ZCL_STATUS_SUCCESS) - { - idleModeInterval = kMinIdleModeInterval; - } + uint32_t idleModeInterval = IcdManagementServer::GetInstance().GetIdleModeInterval(); DeviceLayer::SystemLayer().StartTimer(System::Clock::Timeout(idleModeInterval), OnIdleModeDone, this); System::Clock::Milliseconds32 slowPollInterval = GetSlowPollingInterval(); @@ -138,11 +131,7 @@ void ICDManager::UpdateOperationState(OperationalState state) DeviceLayer::SystemLayer().CancelTimer(OnIdleModeDone, this); mOperationalState = OperationalState::ActiveMode; - uint32_t activeModeInterval = 0; - if (Attributes::ActiveModeInterval::Get(kRootEndpointId, &activeModeInterval) != EMBER_ZCL_STATUS_SUCCESS) - { - activeModeInterval = kMinActiveModeInterval; - } + uint32_t activeModeInterval = IcdManagementServer::GetInstance().GetActiveModeInterval(); DeviceLayer::SystemLayer().StartTimer(System::Clock::Timeout(activeModeInterval), OnActiveModeDone, this); CHIP_ERROR err = DeviceLayer::ConnectivityMgr().SetPollingInterval(GetFastPollingInterval()); @@ -153,11 +142,7 @@ void ICDManager::UpdateOperationState(OperationalState state) } else { - uint16_t activeModeThreshold = 0; - if (Attributes::ActiveModeThreshold::Get(kRootEndpointId, &activeModeThreshold) != EMBER_ZCL_STATUS_SUCCESS) - { - activeModeThreshold = kMinActiveModeThreshold; - } + uint16_t activeModeThreshold = IcdManagementServer::GetInstance().GetActiveModeThreshold(); DeviceLayer::SystemLayer().ExtendTimerTo(System::Clock::Timeout(activeModeThreshold), OnActiveModeDone, this); } } diff --git a/src/app/icd/IcdManagementServer.cpp b/src/app/icd/IcdManagementServer.cpp new file mode 100644 index 00000000000000..4d6c11c8e76c08 --- /dev/null +++ b/src/app/icd/IcdManagementServer.cpp @@ -0,0 +1,81 @@ +#include "IcdManagementServer.h" +#include + +using namespace chip; +using namespace chip::Protocols; + +namespace chip { + +IcdManagementServer IcdManagementServer::mInstance; + +Status IcdManagementServer::RegisterClient(PersistentStorageDelegate & storage, FabricIndex fabric_index, chip::NodeId node_id, + uint64_t monitored_subject, chip::ByteSpan key, + Optional verification_key, bool is_admin) +{ + IcdMonitoringTable table(storage, fabric_index, GetClientsSupportedPerFabric()); + + // Get current entry, if exists + IcdMonitoringEntry entry; + CHIP_ERROR err = table.Find(node_id, entry); + if (CHIP_NO_ERROR == err) + { + // Existing entry: Validate Key if, and only if, the ISD has NOT administrator permissions + if (!is_admin) + { + VerifyOrReturnError(verification_key.HasValue(), InteractionModel::Status::Failure); + VerifyOrReturnError(verification_key.Value().data_equal(entry.key), InteractionModel::Status::Failure); + } + } + else if (CHIP_ERROR_NOT_FOUND == err) + { + // New entry + VerifyOrReturnError(entry.index < table.Limit(), InteractionModel::Status::ResourceExhausted); + } + else + { + // Error + return InteractionModel::Status::Failure; + } + + // Save + entry.checkInNodeID = node_id; + entry.monitoredSubject = monitored_subject; + entry.key = key; + err = table.Set(entry.index, entry); + VerifyOrReturnError(CHIP_ERROR_INVALID_ARGUMENT != err, InteractionModel::Status::ConstraintError); + VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); + + return InteractionModel::Status::Success; +} + +Status IcdManagementServer::UnregisterClient(PersistentStorageDelegate & storage, FabricIndex fabric_index, chip::NodeId node_id, + Optional key, bool is_admin) +{ + IcdMonitoringTable table(storage, fabric_index, GetClientsSupportedPerFabric()); + + // Get current entry, if exists + IcdMonitoringEntry entry; + CHIP_ERROR err = table.Find(node_id, entry); + VerifyOrReturnError(CHIP_ERROR_NOT_FOUND != err, InteractionModel::Status::NotFound); + VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); + + // Existing entry: Validate Key if, and only if, the ISD has NOT administrator permissions + if (!is_admin) + { + VerifyOrReturnError(key.HasValue(), InteractionModel::Status::Failure); + VerifyOrReturnError(key.Value().data_equal(entry.key), InteractionModel::Status::Failure); + } + + err = table.Remove(entry.index); + VerifyOrReturnError(CHIP_NO_ERROR == err, InteractionModel::Status::Failure); + + return InteractionModel::Status::Success; +} + +Status IcdManagementServer::StayActiveRequest(FabricIndex fabric_index) +{ + // TODO: Implementent stay awake logic for end device + return InteractionModel::Status::UnsupportedCommand; +} + +} // namespace chip diff --git a/src/app/icd/IcdManagementServer.h b/src/app/icd/IcdManagementServer.h new file mode 100644 index 00000000000000..8d7f4b2030307a --- /dev/null +++ b/src/app/icd/IcdManagementServer.h @@ -0,0 +1,76 @@ +/** + * + * Copyright (c) 2022 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. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace chip { + +using chip::Protocols::InteractionModel::Status; + +class IcdManagementServer +{ +public: + void Init(uint32_t idle_interval, uint32_t active_interval, uint16_t active_threshold, uint32_t count, + uint16_t fabric_clients_supported) + { + mIdleInterval = idle_interval; + mActiveInterval = active_interval; + mActiveThreshold = active_threshold; + mIcdCounter = count; + mFabricClientsSupported = fabric_clients_supported; + } + + uint32_t GetIdleModeInterval() { return mIdleInterval; } + + uint32_t GetActiveModeInterval() { return mActiveInterval; } + + uint16_t GetActiveModeThreshold() { return mActiveThreshold; } + + uint32_t GetICDCounter() { return mIcdCounter; } + + void SetICDCounter(uint32_t count) { mIcdCounter = count; } + + uint16_t GetClientsSupportedPerFabric() { return mFabricClientsSupported; } + + Status RegisterClient(PersistentStorageDelegate & storage, FabricIndex fabric_index, chip::NodeId node_id, + uint64_t monitored_subject, chip::ByteSpan key, Optional verification_key, bool is_admin); + + Status UnregisterClient(PersistentStorageDelegate & storage, FabricIndex fabric_index, chip::NodeId node_id, + Optional key, bool is_admin); + + Status StayActiveRequest(FabricIndex fabric_index); + + static IcdManagementServer & GetInstance() { return mInstance; } + +private: + IcdManagementServer() = default; + + static IcdManagementServer mInstance; + uint32_t mIdleInterval = CHIP_CONFIG_ICD_IDLE_MODE_INTERVAL; + uint32_t mActiveInterval = CHIP_CONFIG_ICD_ACTIVE_MODE_INTERVAL; + uint16_t mActiveThreshold = CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD; + uint32_t mIcdCounter = 0; + uint16_t mFabricClientsSupported = CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC; +}; + +} // namespace chip diff --git a/src/app/icd/IcdMonitoringTable.cpp b/src/app/icd/IcdMonitoringTable.cpp index e861e78c2cbf2d..ad8cb7d3c4c550 100644 --- a/src/app/icd/IcdMonitoringTable.cpp +++ b/src/app/icd/IcdMonitoringTable.cpp @@ -3,6 +3,13 @@ namespace chip { +enum class Fields : uint8_t +{ + kCheckInNodeID = 1, + kMonitoredSubject = 2, + kKey = 3, +}; + CHIP_ERROR IcdMonitoringEntry::UpdateKey(StorageKeyName & skey) { VerifyOrReturnError(kUndefinedFabricIndex != this->fabricIndex, CHIP_ERROR_INVALID_FABRIC_INDEX); @@ -12,13 +19,48 @@ CHIP_ERROR IcdMonitoringEntry::UpdateKey(StorageKeyName & skey) CHIP_ERROR IcdMonitoringEntry::Serialize(TLV::TLVWriter & writer) const { - return this->EncodeForWrite(writer, TLV::AnonymousTag()); + TLV::TLVType outer; + ReturnErrorOnFailure(writer.StartContainer(TLV::AnonymousTag(), TLV::kTLVType_Structure, outer)); + ReturnErrorOnFailure(writer.Put(TLV::ContextTag(Fields::kCheckInNodeID), checkInNodeID)); + ReturnErrorOnFailure(writer.Put(TLV::ContextTag(Fields::kMonitoredSubject), monitoredSubject)); + ReturnErrorOnFailure(writer.Put(TLV::ContextTag(Fields::kKey), key)); + ReturnErrorOnFailure(writer.EndContainer(outer)); + return CHIP_NO_ERROR; } CHIP_ERROR IcdMonitoringEntry::Deserialize(TLV::TLVReader & reader) { + + CHIP_ERROR err = CHIP_NO_ERROR; + TLV::TLVType outer; + ReturnErrorOnFailure(reader.Next(TLV::AnonymousTag())); - return this->Decode(reader); + VerifyOrReturnError(TLV::kTLVType_Structure == reader.GetType(), CHIP_ERROR_WRONG_TLV_TYPE); + ReturnErrorOnFailure(reader.EnterContainer(outer)); + while ((err = reader.Next()) == CHIP_NO_ERROR) + { + if (TLV::IsContextTag(reader.GetTag())) + { + switch (TLV::TagNumFromTag(reader.GetTag())) + { + case to_underlying(Fields::kCheckInNodeID): + ReturnErrorOnFailure(reader.Get(checkInNodeID)); + break; + case to_underlying(Fields::kMonitoredSubject): + ReturnErrorOnFailure(reader.Get(monitoredSubject)); + break; + case to_underlying(Fields::kKey): + ReturnErrorOnFailure(reader.Get(key)); + break; + default: + break; + } + } + } + + VerifyOrReturnError(err == CHIP_END_OF_TLV, err); + ReturnErrorOnFailure(reader.ExitContainer(outer)); + return CHIP_NO_ERROR; } void IcdMonitoringEntry::Clear() diff --git a/src/app/icd/IcdMonitoringTable.h b/src/app/icd/IcdMonitoringTable.h index a3a144937b4b04..0bfb311207c0d5 100644 --- a/src/app/icd/IcdMonitoringTable.h +++ b/src/app/icd/IcdMonitoringTable.h @@ -16,8 +16,6 @@ */ #pragma once -#include -#include #include #include #include @@ -29,8 +27,7 @@ namespace chip { constexpr size_t kIcdMonitoringBufferSize = 40; -struct IcdMonitoringEntry : public PersistentData, - chip::app::Clusters::IcdManagement::Structs::MonitoringRegistrationStruct::Type +struct IcdMonitoringEntry : public PersistentData { static constexpr size_t kKeyMaxSize = 16; @@ -41,12 +38,15 @@ struct IcdMonitoringEntry : public PersistentData, this->monitoredSubject = nodeId; } bool IsValid() { return this->checkInNodeID != kUndefinedNodeId && this->fabricIndex != kUndefinedFabricIndex; } - CHIP_ERROR UpdateKey(StorageKeyName & key) override; CHIP_ERROR Serialize(TLV::TLVWriter & writer) const override; CHIP_ERROR Deserialize(TLV::TLVReader & reader) override; void Clear() override; + chip::FabricIndex fabricIndex = static_cast(0); + chip::NodeId checkInNodeID = static_cast(0); + uint64_t monitoredSubject = static_cast(0); + chip::ByteSpan key; uint16_t index = 0; }; diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index 03834cd62bd189..f4267b14bd802e 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -176,8 +176,8 @@ chip_test_suite("tests") { ":time-sync-data-provider-test-srcs", "${chip_root}/src/app", "${chip_root}/src/app/common:cluster-objects", + "${chip_root}/src/app/icd:cluster-srcs", "${chip_root}/src/app/icd:manager-srcs", - "${chip_root}/src/app/icd:monitoring-table", "${chip_root}/src/app/tests:helpers", "${chip_root}/src/app/util/mock:mock_ember", "${chip_root}/src/lib/core", 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 667bcd88787da3..8b5327671091b4 100644 --- a/src/app/zap-templates/zcl/zcl-with-test-extensions.json +++ b/src/app/zap-templates/zcl/zcl-with-test-extensions.json @@ -194,6 +194,14 @@ "MaxGroupKeysPerFabric", "FeatureMap" ], + "ICD Management": [ + "IdleModeInterval", + "ActiveModeInterval", + "ActiveModeThreshold", + "RegisteredClients", + "ICDCounter", + "ClientsSupportedPerFabric" + ], "Operational Credentials": [ "SupportedFabrics", "CommissionedFabrics", diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json index 8ece026c28f933..dbe44dfb9e6745 100644 --- a/src/app/zap-templates/zcl/zcl.json +++ b/src/app/zap-templates/zcl/zcl.json @@ -192,6 +192,14 @@ "MaxGroupKeysPerFabric", "FeatureMap" ], + "ICD Management": [ + "IdleModeInterval", + "ActiveModeInterval", + "ActiveModeThreshold", + "RegisteredClients", + "ICDCounter", + "ClientsSupportedPerFabric" + ], "Operational Credentials": [ "SupportedFabrics", "CommissionedFabrics", diff --git a/src/lib/core/CHIPConfig.h b/src/lib/core/CHIPConfig.h index 66ea165e61979f..9ec11778f615c5 100644 --- a/src/lib/core/CHIPConfig.h +++ b/src/lib/core/CHIPConfig.h @@ -1460,6 +1460,42 @@ extern const char CHIP_NON_PRODUCTION_MARKER[]; #define CHIP_CONFIG_SKIP_APP_SPECIFIC_GENERATED_HEADER_INCLUDES 0 #endif +/** + * @def CHIP_CONFIG_ICD_IDLE_MODE_INTERVAL + * + * @brief Default value for the ICD Management cluster IdleModeInterval attribute, in milliseconds + */ +#ifndef CHIP_CONFIG_ICD_IDLE_MODE_INTERVAL +#define CHIP_CONFIG_ICD_IDLE_MODE_INTERVAL 500 +#endif + +/** + * @def CHIP_CONFIG_ICD_ACTIVE_MODE_INTERVAL + * + * @brief Default value for the ICD Management cluster ActiveModeInterval attribute, in milliseconds + */ +#ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_INTERVAL +#define CHIP_CONFIG_ICD_ACTIVE_MODE_INTERVAL 300 +#endif + +/** + * @def CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD + * + * @brief Default value for the ICD Management cluster ActiveModeThreshold attribute, in milliseconds + */ +#ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD +#define CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD 300 +#endif + +/** + * @def CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC + * + * @brief Default value for the ICD Management cluster ClientsSupportedPerFabric attribute, in milliseconds + */ +#ifndef CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC +#define CHIP_CONFIG_ICD_CLIENTS_SUPPORTED_PER_FABRIC 2 +#endif + /** * @} */ 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 69ca37ec5fb4a0..6cabdc7632fc50 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 @@ -6632,161 +6632,6 @@ EmberAfStatus Set(chip::EndpointId endpoint, uint16_t value) namespace IcdManagement { namespace Attributes { -namespace IdleModeInterval { - -EmberAfStatus Get(chip::EndpointId endpoint, uint32_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - EmberAfStatus status = emberAfReadAttribute(endpoint, Clusters::IcdManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; - } - *value = Traits::StorageToWorking(temp); - return status; -} -EmberAfStatus Set(chip::EndpointId endpoint, uint32_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::IcdManagement::Id, Id, writable, ZCL_INT32U_ATTRIBUTE_TYPE); -} - -} // namespace IdleModeInterval - -namespace ActiveModeInterval { - -EmberAfStatus Get(chip::EndpointId endpoint, uint32_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - EmberAfStatus status = emberAfReadAttribute(endpoint, Clusters::IcdManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; - } - *value = Traits::StorageToWorking(temp); - return status; -} -EmberAfStatus Set(chip::EndpointId endpoint, uint32_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::IcdManagement::Id, Id, writable, ZCL_INT32U_ATTRIBUTE_TYPE); -} - -} // namespace ActiveModeInterval - -namespace ActiveModeThreshold { - -EmberAfStatus Get(chip::EndpointId endpoint, uint16_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - EmberAfStatus status = emberAfReadAttribute(endpoint, Clusters::IcdManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; - } - *value = Traits::StorageToWorking(temp); - return status; -} -EmberAfStatus Set(chip::EndpointId endpoint, uint16_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::IcdManagement::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE); -} - -} // namespace ActiveModeThreshold - -namespace ICDCounter { - -EmberAfStatus Get(chip::EndpointId endpoint, uint32_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - EmberAfStatus status = emberAfReadAttribute(endpoint, Clusters::IcdManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; - } - *value = Traits::StorageToWorking(temp); - return status; -} -EmberAfStatus Set(chip::EndpointId endpoint, uint32_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::IcdManagement::Id, Id, writable, ZCL_INT32U_ATTRIBUTE_TYPE); -} - -} // namespace ICDCounter - -namespace ClientsSupportedPerFabric { - -EmberAfStatus Get(chip::EndpointId endpoint, uint16_t * value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - EmberAfStatus status = emberAfReadAttribute(endpoint, Clusters::IcdManagement::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, status); - if (!Traits::CanRepresentValue(/* isNullable = */ false, temp)) - { - return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; - } - *value = Traits::StorageToWorking(temp); - return status; -} -EmberAfStatus Set(chip::EndpointId endpoint, uint16_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ false, value)) - { - return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::IcdManagement::Id, Id, writable, ZCL_INT16U_ATTRIBUTE_TYPE); -} - -} // namespace ClientsSupportedPerFabric - namespace FeatureMap { EmberAfStatus Get(chip::EndpointId endpoint, uint32_t * value) 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 e8e5b4e0669913..95707374728192 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 @@ -1282,31 +1282,6 @@ EmberAfStatus Set(chip::EndpointId endpoint, uint16_t value); namespace IcdManagement { namespace Attributes { -namespace IdleModeInterval { -EmberAfStatus Get(chip::EndpointId endpoint, uint32_t * value); // int32u -EmberAfStatus Set(chip::EndpointId endpoint, uint32_t value); -} // namespace IdleModeInterval - -namespace ActiveModeInterval { -EmberAfStatus Get(chip::EndpointId endpoint, uint32_t * value); // int32u -EmberAfStatus Set(chip::EndpointId endpoint, uint32_t value); -} // namespace ActiveModeInterval - -namespace ActiveModeThreshold { -EmberAfStatus Get(chip::EndpointId endpoint, uint16_t * value); // int16u -EmberAfStatus Set(chip::EndpointId endpoint, uint16_t value); -} // namespace ActiveModeThreshold - -namespace ICDCounter { -EmberAfStatus Get(chip::EndpointId endpoint, uint32_t * value); // int32u -EmberAfStatus Set(chip::EndpointId endpoint, uint32_t value); -} // namespace ICDCounter - -namespace ClientsSupportedPerFabric { -EmberAfStatus Get(chip::EndpointId endpoint, uint16_t * value); // int16u -EmberAfStatus Set(chip::EndpointId endpoint, uint16_t value); -} // namespace ClientsSupportedPerFabric - namespace FeatureMap { EmberAfStatus Get(chip::EndpointId endpoint, uint32_t * value); // bitmap32 EmberAfStatus Set(chip::EndpointId endpoint, uint32_t value);