From 263872277a1cbb15487279794ebed43a2a1c004b Mon Sep 17 00:00:00 2001 From: Karsten Sperling Date: Thu, 16 May 2024 14:30:05 +1200 Subject: [PATCH] Add ServerCluster base class and Ember adapter --- src/app/BUILD.gn | 2 + src/app/ServerCluster.cpp | 58 ++++++++++ src/app/ServerCluster.h | 108 ++++++++++++++++++ src/app/util/BUILD.gn | 1 + src/app/util/ember-server-cluster.h | 50 ++++++++ .../zap-templates/templates/app/callback.zapt | 7 ++ 6 files changed, 226 insertions(+) create mode 100644 src/app/ServerCluster.cpp create mode 100644 src/app/ServerCluster.h create mode 100644 src/app/util/ember-server-cluster.h diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index 55bc5f305ddd99..28eb9dfe5ea5b5 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -382,6 +382,8 @@ static_library("app") { "OTAUserConsentCommon.h", "ReadHandler.cpp", "SafeAttributePersistenceProvider.h", + "ServerCluster.cpp", + "ServerCluster.h", "TimerDelegates.cpp", "TimerDelegates.h", "WriteHandler.cpp", diff --git a/src/app/ServerCluster.cpp b/src/app/ServerCluster.cpp new file mode 100644 index 00000000000000..d5302f4d471bbc --- /dev/null +++ b/src/app/ServerCluster.cpp @@ -0,0 +1,58 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +namespace chip { +namespace app { + +ServerCluster::ServerCluster(EndpointId aEndpointId, ClusterId aClusterId) : + AttributeAccessInterface(MakeOptional(aEndpointId), aClusterId), CommandHandlerInterface(MakeOptional(aEndpointId), aClusterId) +{} + +CHIP_ERROR ServerCluster::Init() +{ + ChipLogError(NotSpecified, "CLUStER INIT"); + ReturnErrorOnFailure(InteractionModelEngine::GetInstance()->RegisterCommandHandler(this)); + VerifyOrReturnError(registerAttributeAccessOverride(this), CHIP_ERROR_INCORRECT_STATE); + return CHIP_NO_ERROR; +} + +void ServerCluster::Shutdown() +{ + InteractionModelEngine::GetInstance()->UnregisterCommandHandler(this); + unregisterAttributeAccessOverride(this); +} + +void EmberClusterAdapterImpl::Init(ServerCluster & cluster) +{ + CHIP_ERROR err = cluster.Init(); + VerifyOrDieWithMsg(err == CHIP_NO_ERROR, Zcl, "Cluster initialization failed: %" CHIP_ERROR_FORMAT, err.Format()); +} + +void EmberClusterAdapterImpl::InitFailureInstancesExceeded() +{ + VerifyOrDieWithMsg(false, Zcl, "Cluster initialization failed: no instance allocated"); +} + +} // namespace app +} // namespace chip diff --git a/src/app/ServerCluster.h b/src/app/ServerCluster.h new file mode 100644 index 00000000000000..07c74f678e8d2f --- /dev/null +++ b/src/app/ServerCluster.h @@ -0,0 +1,108 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include +#include + +namespace chip { +namespace app { + +/** + * Base class for server-side cluster implementations. + */ +class ServerCluster : protected AttributeAccessInterface, protected CommandHandlerInterface +{ +public: + ServerCluster(EndpointId aEndpointId, ClusterId aClusterId); + virtual ~ServerCluster() { Shutdown(); } + + EndpointId GetEndpointId() { return mEndpointId; } + + virtual CHIP_ERROR Init(); + virtual void Shutdown(); + +protected: + void InvokeCommand(HandlerContext & handlerContext) override {}; + +private: + EndpointId mEndpointId; +}; + +/** + * An adapter class that statically allocates memory for a fixed number of cluster instances + * and manages their lifecycle. + * + * @see DECLARE_CLUSTER_SERVER() + */ +template +class EmberClusterAdapter; + +class EmberClusterAdapterImpl +{ + template + friend class EmberClusterAdapter; + + static void Init(ServerCluster & cluster); + static void InitFailureInstancesExceeded(); +}; + +template +class EmberClusterAdapter final +{ + static_assert(std::is_base_of_v); + +public: + constexpr EmberClusterAdapter() = default; + + void Init(EndpointId endpoint) + { + for (auto & instance : mInstances) + { + if (!instance) + { + EmberClusterAdapterImpl::Init(instance.emplace(endpoint)); + return; + } + } + EmberClusterAdapterImpl::InitFailureInstancesExceeded(); + } + + void Shutdown(EndpointId endpoint) + { + for (auto & instance : mInstances) + { + if (instance && instance->GetEndpointId() == endpoint) + { + instance.reset(); // destructor calls Shutdown + return; + } + } + // ignore silently + } + +private: + std::array, N> mInstances; +}; + +} // namespace app +} // namespace chip diff --git a/src/app/util/BUILD.gn b/src/app/util/BUILD.gn index dccbc68c0d943e..c8440e3644deff 100644 --- a/src/app/util/BUILD.gn +++ b/src/app/util/BUILD.gn @@ -23,6 +23,7 @@ source_set("types") { "attribute-metadata.h", "attribute-storage-null-handling.h", "basic-types.h", + "ember-server-cluster.h", "ember-strings.cpp", "ember-strings.h", "endpoint-config-defines.h", diff --git a/src/app/util/ember-server-cluster.h b/src/app/util/ember-server-cluster.h new file mode 100644 index 00000000000000..ab3037a204b628 --- /dev/null +++ b/src/app/util/ember-server-cluster.h @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +#include +#include + +/** + * Defines static storage for the specified number of instances of the specified class + * (which must be a sub-class of chip::app::ServerCluster) as well as the corresponding Ember + * ServerInitCallback and ShutdownCallback functions. + * + * Note: This macro must be called from the global namespace. + * + * Example: + * DECLARE_SERVER_CLUSTER(DISCO_BALL_CLUSTER, chip::app::Clusters::DiscoBall::Instance); + */ +#define DECLARE_SERVER_CLUSTER(NAME, CLASS) \ + chip::app::EmberClusterAdapter \ + gClusterAdapter_##NAME; \ + void _DECLARE_CLUSTER_CONCAT3(emberAf, MATTER_DM_##NAME##_LABEL, ClusterServerInitCallback)(chip::EndpointId endpoint) \ + { \ + gClusterAdapter_##NAME.Init(endpoint); \ + } \ + void _DECLARE_CLUSTER_CONCAT3(Matter, MATTER_DM_##NAME##_LABEL, ClusterServerShutdownCallback)(chip::EndpointId endpoint) \ + { \ + gClusterAdapter_##NAME.Shutdown(endpoint); \ + } + +#define _DECLARE_CLUSTER_EXPAND(a) a +#define _DECLARE_CLUSTER_CONCAT3_(a, b, c) a##b##c +#define _DECLARE_CLUSTER_CONCAT3(a, b, c) _DECLARE_CLUSTER_CONCAT3_(a, b, c) diff --git a/src/app/zap-templates/templates/app/callback.zapt b/src/app/zap-templates/templates/app/callback.zapt index effd7f2d857164..8d427fefdcb766 100644 --- a/src/app/zap-templates/templates/app/callback.zapt +++ b/src/app/zap-templates/templates/app/callback.zapt @@ -14,6 +14,13 @@ #include #include + +// Cluster Labels + +{{#zcl_clusters}} +#define MATTER_DM_{{as_delimited_macro define}}_LABEL {{asUpperCamelCase label}} +{{/zcl_clusters}} + // Cluster Init Functions {{#zcl_clusters}}