Matter SDK Coverage Report
Current view: top level - data-model-providers/codedriven - CodeDrivenDataModelProvider.h (source / functions) Coverage Total Hit
Test: SHA:48cc3057d373f5189d8404fd2bac3595e32b29b9 Lines: 100.0 % 3 3
Test Date: 2025-09-06 07:10:37 Functions: 100.0 % 1 1

            Line data    Source code
       1              : /*
       2              :  *    Copyright (c) 2025 Project CHIP Authors
       3              :  *    All rights reserved.
       4              :  *
       5              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       6              :  *    you may not use this file except in compliance with the License.
       7              :  *    You may obtain a copy of the License at
       8              :  *
       9              :  *        http://www.apache.org/licenses/LICENSE-2.0
      10              :  *
      11              :  *    Unless required by applicable law or agreed to in writing, software
      12              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      13              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      14              :  *    See the License for the specific language governing permissions and
      15              :  *    limitations under the License.
      16              :  */
      17              : #pragma once
      18              : 
      19              : #include <app/CommandHandlerInterface.h>
      20              : #include <app/ConcreteCommandPath.h>
      21              : #include <app/data-model-provider/ActionReturnStatus.h>
      22              : #include <app/data-model-provider/MetadataTypes.h>
      23              : #include <app/data-model-provider/Provider.h>
      24              : #include <app/persistence/AttributePersistenceProvider.h>
      25              : #include <app/server-cluster/ServerClusterInterface.h>
      26              : #include <app/server-cluster/ServerClusterInterfaceRegistry.h>
      27              : #include <data-model-providers/codedriven/endpoint/EndpointInterface.h>
      28              : #include <data-model-providers/codedriven/endpoint/EndpointInterfaceRegistry.h>
      29              : #include <lib/support/ReadOnlyBuffer.h>
      30              : 
      31              : namespace chip {
      32              : namespace app {
      33              : /**
      34              :  * @brief An implementation of DataModel::Provider that constructs the data model
      35              :  *        programmatically by aggregating EndpointInterface instances.
      36              :  *
      37              :  * This provider allows applications to define their Matter device data model (endpoints,
      38              :  * clusters, attributes, commands) dynamically at runtime. It manages a list of EndpointInterface
      39              :  * objects, each representing an endpoint on the device.
      40              :  *
      41              :  * The expected usage pattern by the application is as follows:
      42              :  * 1. Instantiate ServerClusterInterface(s) and ServerClusterRegistration(s).
      43              :  * 2. Instantiate EndpointInterface(s) and EndpointInterfaceRegistration(s).
      44              :  * 2. Instantiate the CodeDrivenDataModelProvider.
      45              :  * 3. Register ServerClusterInterfaceRegistration(s) to the CodeDrivenDataModelProvider using AddCluster().
      46              :  * 4. Register EndpointInterfaceRegistration(s) to the CodeDrivenDataModelProvider using AddEndpoint().
      47              :  *    Note: Step 4 MUST come after Step 3 (Endpoint needs to know about its clusters).
      48              :  * 5. Call Startup() on the CodeDrivenDataModelProvider.
      49              :  *
      50              :  * Note: if the CodeDrivenDataModelProvider has already been started (runtime change to add/remove Endpoints/Clusters),
      51              :  *       the Startup() method on each ServerClusterInterface will be called when the EndpointInterface is added (Step 4).
      52              :  *       If the provider hasn't been started, the Startup() method will be called when the provider is started (Step 5).
      53              :  *
      54              :  * TODO: Notify composition changes when the provider is started up and endpoints are added/removed at runtime.
      55              :  *       For now, applications are responsible for handling composition changes and calling markDirty() when needed.
      56              :  *
      57              :  * Lifecycle:
      58              :  * - The CodeDrivenDataModelProvider stores raw pointers to EndpointInterface and ServerClusterInterface.
      59              :  *   It does NOT take ownership. Callers must ensure these instances outlive the provider.
      60              :  */
      61              : class CodeDrivenDataModelProvider : public DataModel::Provider
      62              : {
      63              : public:
      64           50 :     CodeDrivenDataModelProvider(PersistentStorageDelegate & storage, AttributePersistenceProvider & attributeStorage) :
      65           50 :         mPersistentStorageDelegate(storage), mAttributePersistenceProvider(attributeStorage)
      66           50 :     {}
      67              : 
      68              :     /* DataModel::Provider implementation */
      69              :     CHIP_ERROR Startup(DataModel::InteractionModelContext context) override;
      70              :     CHIP_ERROR Shutdown() override;
      71              : 
      72              :     DataModel::ActionReturnStatus ReadAttribute(const DataModel::ReadAttributeRequest & request,
      73              :                                                 AttributeValueEncoder & encoder) override;
      74              :     DataModel::ActionReturnStatus WriteAttribute(const DataModel::WriteAttributeRequest & request,
      75              :                                                  AttributeValueDecoder & decoder) override;
      76              : 
      77              :     void ListAttributeWriteNotification(const ConcreteAttributePath & path, DataModel::ListWriteOperation opType) override;
      78              :     std::optional<DataModel::ActionReturnStatus> InvokeCommand(const DataModel::InvokeRequest & request,
      79              :                                                                TLV::TLVReader & input_arguments, CommandHandler * handler) override;
      80              : 
      81              :     /* ProviderMetadataTree implementation */
      82              :     CHIP_ERROR Endpoints(ReadOnlyBufferBuilder<DataModel::EndpointEntry> & out) override;
      83              :     CHIP_ERROR SemanticTags(EndpointId endpointId,
      84              :                             ReadOnlyBufferBuilder<Clusters::Descriptor::Structs::SemanticTagStruct::Type> & out) override;
      85              :     CHIP_ERROR DeviceTypes(EndpointId endpointId, ReadOnlyBufferBuilder<DataModel::DeviceTypeEntry> & out) override;
      86              :     CHIP_ERROR ClientClusters(EndpointId endpointId, ReadOnlyBufferBuilder<ClusterId> & out) override;
      87              :     CHIP_ERROR ServerClusters(EndpointId endpointId, ReadOnlyBufferBuilder<DataModel::ServerClusterEntry> & out) override;
      88              :     CHIP_ERROR GeneratedCommands(const ConcreteClusterPath & path, ReadOnlyBufferBuilder<CommandId> & out) override;
      89              :     CHIP_ERROR AcceptedCommands(const ConcreteClusterPath & path,
      90              :                                 ReadOnlyBufferBuilder<DataModel::AcceptedCommandEntry> & out) override;
      91              :     CHIP_ERROR Attributes(const ConcreteClusterPath & path, ReadOnlyBufferBuilder<DataModel::AttributeEntry> & builder) override;
      92              :     CHIP_ERROR EventInfo(const ConcreteEventPath & path, DataModel::EventEntry & eventInfo) override;
      93              :     void Temporary_ReportAttributeChanged(const AttributePathParams & path) override;
      94              : 
      95              :     /**
      96              :      * @brief Adds an endpoint to the data model provider.
      97              :      *
      98              :      * This method registers an endpoint, making it part of the device's data model.
      99              :      * If the provider has already been started, this may trigger a Startup() call on
     100              :      * each ServerClusterInterface associated with the endpoint.
     101              :      * The Startup() call on the associated clusters will ONLY happen if this is the first
     102              :      * endpoint associated with the cluster (i.e. ServerClusterInterface.GetPaths() returns
     103              :      * at least one path with endpoint ID == registration.endpointEntry.id, and none
     104              :      * of the other endpoints in GetPaths() are registered yet). This ensures
     105              :      * the cluster is only started once, even if it is associated with multiple endpoints.
     106              :      *
     107              :      * Prerequisites:
     108              :      *   - It MUST be called after all clusters for the endpoint have been registered with
     109              :      *     AddCluster().
     110              :      *   - The provided `registration` (EndpointInterfaceRegistration) must not already be
     111              :      *     part of another list (i.e., `registration.next` must be nullptr).
     112              :      *   - The EndpointInterface within the `registration` must be valid (i.e.,
     113              :      *     `registration.endpointInterface` must not be nullptr).
     114              :      *   - The `registration.endpointEntry.id` must be valid (not `kInvalidEndpointId` and
     115              :      *     not used by another endpoint).
     116              :      *   - The LIFETIME of `registration` must outlive the provider (or the registration must
     117              :      *     be removed using `RemoveEndpoint` before it goes away).
     118              :      *
     119              :      * @param registration The registration object for the endpoint, containing a valid
     120              :      *                     EndpointInterface and Endpoint ID.
     121              :      * @return CHIP_NO_ERROR on success.
     122              :      *         CHIP_ERROR_INVALID_ARGUMENT if `registration.next` is not nullptr or
     123              :      *                                     `registration.endpointInterface` is nullptr or
     124              :      *                                     `registration.endpointEntry.id` is kInvalidEndpointId.
     125              :      *         CHIP_ERROR_DUPLICATE_KEY_ID if `registration.endpointEntry.id` is already in use.
     126              :      */
     127              :     CHIP_ERROR AddEndpoint(EndpointInterfaceRegistration & registration);
     128              : 
     129              :     /**
     130              :      * @brief Removes an endpoint from the data model provider.
     131              :      *
     132              :      * This method unregisters an endpoint, removing it from the device's data model.
     133              :      * If the provider has already been started, this might trigger a Shutdown() call on
     134              :      * each ServerClusterInterface associated with the endpoint.
     135              :      * The Shutdown() call on the associated clusters will ONLY happen if this is the last
     136              :      * endpoint associated with the cluster (i.e. ServerClusterInterface.GetPaths() returns
     137              :      * no paths with valid Endpoint IDs).
     138              :      *
     139              :      * Note: Removing an Endpoint does not remove any clusters associated with the endpoint.
     140              :      *       Those can be removed using RemoveCluster() AFTER the endpoint has been removed.
     141              : 
     142              :      * Prerequisites:
     143              :      *   - It MUST be called BEFORE removing associted clusters with RemoveCluster() to guarantee
     144              :      *     the endpoint removal is atomic.
     145              :      *   - The endpoint ID must be valid.
     146              :      *
     147              :      * @param endpointId The ID of the endpoint to remove.
     148              :      * @return CHIP_NO_ERROR on success.
     149              :      *         CHIP_ERROR_NOT_FOUND if no endpoint with the given ID is registered.
     150              :      *         CHIP_ERROR_INVALID_ARGUMENT if endpointId is kInvalidEndpointId.
     151              :      */
     152              :     CHIP_ERROR RemoveEndpoint(EndpointId endpointId);
     153              : 
     154              :     /**
     155              :      * @brief Add a ServerClusterInterface to the Data Model Provider.
     156              :      *
     157              :      * Requirements:
     158              :      *   - entry MUST NOT be part of any other registration
     159              :      *   - paths MUST NOT be part of any other ServerClusterInterface (i.e. only a single
     160              :      *     registration for a given `endpointId/clusterId` path).
     161              :      *   - The LIFETIME of entry must outlive the provider (or the entry must be unregistered
     162              :      *     via RemoveCluster before it goes away).
     163              :      *   - If the provider has already been started, this method must be called prior to
     164              :      *     calling AddEndpoint() (i.e. the `endpointId` of all paths in `entry.GetPaths()`
     165              :      *     must NOT be registered in the provider yet), otherwise this would cause non-atomic
     166              :      *     changes to an endpoint, which is not allowed.
     167              :      *
     168              :      * @param entry The ServerClusterRegistration containing the cluster to register.
     169              :      * @return CHIP_NO_ERROR on success.
     170              :      *         CHIP_ERROR_INVALID_ARGUMENT if `entry.next` is not `nullptr` or
     171              :      *                                     `entry.serverClusterInterface` is `nullptr` or
     172              :      *                                     `entry.serverClusterInterface.GetPaths()` is empty/invalid.
     173              :      *         CHIP_ERROR_DUPLICATE_KEY_ID if the cluster is already registered.
     174              :      *         CHIP_ERROR_INCORRECT_STATE if the provider has been started and an endpoint for
     175              :      *                                    one of the cluster paths has already been registered.
     176              :      */
     177              :     CHIP_ERROR AddCluster(ServerClusterRegistration & entry);
     178              : 
     179              :     /**
     180              :      * @brief Remove a ServerClusterInterface from the Data Model Provider.
     181              :      *
     182              :      * To avoid violating the requirement of non-atomic changes to endpoints, this SHALL only be
     183              :      * called after all endpoints associated with the cluster have been removed using RemoveEndpoint().
     184              :      *
     185              :      * Requirements:
     186              :      *   - entry MUST be valid
     187              :      *   - The `endpointId` of all paths in `entry.GetPaths()` are no longer registered in the provider.
     188              :      *
     189              :      * @param entry The ServerClusterInterface to remove.
     190              :      * @return CHIP_NO_ERROR on success.
     191              :      *         CHIP_ERROR_INVALID_ARGUMENT if `entry` is nullptr.
     192              :      *         CHIP_ERROR_NOT_FOUND if the entry is not registered.
     193              :      *         CHIP_ERROR_INCORRECT_STATE if an endpoint for one of the cluster paths is still registered.
     194              :      */
     195              :     CHIP_ERROR RemoveCluster(ServerClusterInterface * entry);
     196              : 
     197              : private:
     198              :     EndpointInterfaceRegistry mEndpointInterfaceRegistry;
     199              :     ServerClusterInterfaceRegistry mServerClusterRegistry;
     200              :     std::optional<ServerClusterContext> mServerClusterContext;
     201              :     std::optional<DataModel::InteractionModelContext> mInteractionModelContext;
     202              :     PersistentStorageDelegate & mPersistentStorageDelegate;
     203              :     AttributePersistenceProvider & mAttributePersistenceProvider;
     204              : 
     205              :     /// Return the interface registered for the given endpoint ID or nullptr if one does not exist
     206              :     EndpointInterface * GetEndpointInterface(EndpointId endpointId);
     207              : 
     208              :     /// Return the interface registered for the given cluster path or nullptr if one does not exist
     209              :     ServerClusterInterface * GetServerClusterInterface(const ConcreteClusterPath & path);
     210              : };
     211              : 
     212              : } // namespace app
     213              : } // namespace chip
        

Generated by: LCOV version 2.0-1