Matter SDK Coverage Report
Current view: top level - data-model-providers/codedriven - CodeDrivenDataModelProvider.h (source / functions) Coverage Total Hit
Test: SHA:3108862db59e5fa02f4a254cea1d5089c60155eb Lines: 100.0 % 3 3
Test Date: 2025-10-12 07:08:15 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, ReadOnlyBufferBuilder<SemanticTag> & out) override;
      84              :     CHIP_ERROR DeviceTypes(EndpointId endpointId, ReadOnlyBufferBuilder<DataModel::DeviceTypeEntry> & out) override;
      85              :     CHIP_ERROR ClientClusters(EndpointId endpointId, ReadOnlyBufferBuilder<ClusterId> & out) override;
      86              :     CHIP_ERROR ServerClusters(EndpointId endpointId, ReadOnlyBufferBuilder<DataModel::ServerClusterEntry> & out) override;
      87              :     CHIP_ERROR GeneratedCommands(const ConcreteClusterPath & path, ReadOnlyBufferBuilder<CommandId> & out) override;
      88              :     CHIP_ERROR AcceptedCommands(const ConcreteClusterPath & path,
      89              :                                 ReadOnlyBufferBuilder<DataModel::AcceptedCommandEntry> & out) override;
      90              :     CHIP_ERROR Attributes(const ConcreteClusterPath & path, ReadOnlyBufferBuilder<DataModel::AttributeEntry> & builder) override;
      91              :     CHIP_ERROR EventInfo(const ConcreteEventPath & path, DataModel::EventEntry & eventInfo) override;
      92              :     void Temporary_ReportAttributeChanged(const AttributePathParams & path) override;
      93              : 
      94              :     /**
      95              :      * @brief Adds an endpoint to the data model provider.
      96              :      *
      97              :      * This method registers an endpoint, making it part of the device's data model.
      98              :      * If the provider has already been started, this may trigger a Startup() call on
      99              :      * each ServerClusterInterface associated with the endpoint.
     100              :      * The Startup() call on the associated clusters will ONLY happen if this is the first
     101              :      * endpoint associated with the cluster (i.e. ServerClusterInterface.GetPaths() returns
     102              :      * at least one path with endpoint ID == registration.endpointEntry.id, and none
     103              :      * of the other endpoints in GetPaths() are registered yet). This ensures
     104              :      * the cluster is only started once, even if it is associated with multiple endpoints.
     105              :      *
     106              :      * Prerequisites:
     107              :      *   - It MUST be called after all clusters for the endpoint have been registered with
     108              :      *     AddCluster().
     109              :      *   - The provided `registration` (EndpointInterfaceRegistration) must not already be
     110              :      *     part of another list (i.e., `registration.next` must be nullptr).
     111              :      *   - The EndpointInterface within the `registration` must be valid (i.e.,
     112              :      *     `registration.endpointInterface` must not be nullptr).
     113              :      *   - The `registration.endpointEntry.id` must be valid (not `kInvalidEndpointId` and
     114              :      *     not used by another endpoint).
     115              :      *   - The LIFETIME of `registration` must outlive the provider (or the registration must
     116              :      *     be removed using `RemoveEndpoint` before it goes away).
     117              :      *
     118              :      * @param registration The registration object for the endpoint, containing a valid
     119              :      *                     EndpointInterface and Endpoint ID.
     120              :      * @return CHIP_NO_ERROR on success.
     121              :      *         CHIP_ERROR_INVALID_ARGUMENT if `registration.next` is not nullptr or
     122              :      *                                     `registration.endpointInterface` is nullptr or
     123              :      *                                     `registration.endpointEntry.id` is kInvalidEndpointId.
     124              :      *         CHIP_ERROR_DUPLICATE_KEY_ID if `registration.endpointEntry.id` is already in use.
     125              :      */
     126              :     CHIP_ERROR AddEndpoint(EndpointInterfaceRegistration & registration);
     127              : 
     128              :     /**
     129              :      * @brief Removes an endpoint from the data model provider.
     130              :      *
     131              :      * This method unregisters an endpoint, removing it from the device's data model.
     132              :      * If the provider has already been started, this might trigger a Shutdown() call on
     133              :      * each ServerClusterInterface associated with the endpoint.
     134              :      * The Shutdown() call on the associated clusters will ONLY happen if this is the last
     135              :      * endpoint associated with the cluster (i.e. ServerClusterInterface.GetPaths() returns
     136              :      * no paths with valid Endpoint IDs).
     137              :      *
     138              :      * Note: Removing an Endpoint does not remove any clusters associated with the endpoint.
     139              :      *       Those can be removed using RemoveCluster() AFTER the endpoint has been removed.
     140              : 
     141              :      * Prerequisites:
     142              :      *   - It MUST be called BEFORE removing associted clusters with RemoveCluster() to guarantee
     143              :      *     the endpoint removal is atomic.
     144              :      *   - The endpoint ID must be valid.
     145              :      *
     146              :      * @param endpointId The ID of the endpoint to remove.
     147              :      * @return CHIP_NO_ERROR on success.
     148              :      *         CHIP_ERROR_NOT_FOUND if no endpoint with the given ID is registered.
     149              :      *         CHIP_ERROR_INVALID_ARGUMENT if endpointId is kInvalidEndpointId.
     150              :      */
     151              :     CHIP_ERROR RemoveEndpoint(EndpointId endpointId);
     152              : 
     153              :     /**
     154              :      * @brief Add a ServerClusterInterface to the Data Model Provider.
     155              :      *
     156              :      * Requirements:
     157              :      *   - entry MUST NOT be part of any other registration
     158              :      *   - paths MUST NOT be part of any other ServerClusterInterface (i.e. only a single
     159              :      *     registration for a given `endpointId/clusterId` path).
     160              :      *   - The LIFETIME of entry must outlive the provider (or the entry must be unregistered
     161              :      *     via RemoveCluster before it goes away).
     162              :      *   - If the provider has already been started, this method must be called prior to
     163              :      *     calling AddEndpoint() (i.e. the `endpointId` of all paths in `entry.GetPaths()`
     164              :      *     must NOT be registered in the provider yet), otherwise this would cause non-atomic
     165              :      *     changes to an endpoint, which is not allowed.
     166              :      *
     167              :      * @param entry The ServerClusterRegistration containing the cluster to register.
     168              :      * @return CHIP_NO_ERROR on success.
     169              :      *         CHIP_ERROR_INVALID_ARGUMENT if `entry.next` is not `nullptr` or
     170              :      *                                     `entry.serverClusterInterface` is `nullptr` or
     171              :      *                                     `entry.serverClusterInterface.GetPaths()` is empty/invalid.
     172              :      *         CHIP_ERROR_DUPLICATE_KEY_ID if the cluster is already registered.
     173              :      *         CHIP_ERROR_INCORRECT_STATE if the provider has been started and an endpoint for
     174              :      *                                    one of the cluster paths has already been registered.
     175              :      */
     176              :     CHIP_ERROR AddCluster(ServerClusterRegistration & entry);
     177              : 
     178              :     /**
     179              :      * @brief Remove a ServerClusterInterface from the Data Model Provider.
     180              :      *
     181              :      * To avoid violating the requirement of non-atomic changes to endpoints, this SHALL only be
     182              :      * called after all endpoints associated with the cluster have been removed using RemoveEndpoint().
     183              :      *
     184              :      * Requirements:
     185              :      *   - entry MUST be valid
     186              :      *   - The `endpointId` of all paths in `entry.GetPaths()` are no longer registered in the provider.
     187              :      *
     188              :      * @param entry The ServerClusterInterface to remove.
     189              :      * @return CHIP_NO_ERROR on success.
     190              :      *         CHIP_ERROR_INVALID_ARGUMENT if `entry` is nullptr.
     191              :      *         CHIP_ERROR_NOT_FOUND if the entry is not registered.
     192              :      *         CHIP_ERROR_INCORRECT_STATE if an endpoint for one of the cluster paths is still registered.
     193              :      */
     194              :     CHIP_ERROR RemoveCluster(ServerClusterInterface * entry);
     195              : 
     196              : private:
     197              :     EndpointInterfaceRegistry mEndpointInterfaceRegistry;
     198              :     ServerClusterInterfaceRegistry mServerClusterRegistry;
     199              :     std::optional<ServerClusterContext> mServerClusterContext;
     200              :     std::optional<DataModel::InteractionModelContext> mInteractionModelContext;
     201              :     PersistentStorageDelegate & mPersistentStorageDelegate;
     202              :     AttributePersistenceProvider & mAttributePersistenceProvider;
     203              : 
     204              :     /// Return the interface registered for the given endpoint ID or nullptr if one does not exist
     205              :     EndpointInterface * GetEndpointInterface(EndpointId endpointId);
     206              : 
     207              :     /// Return the interface registered for the given cluster path or nullptr if one does not exist
     208              :     ServerClusterInterface * GetServerClusterInterface(const ConcreteClusterPath & path);
     209              : };
     210              : 
     211              : } // namespace app
     212              : } // namespace chip
        

Generated by: LCOV version 2.0-1