Matter SDK Coverage Report
Current view: top level - controller - ReadInteraction.h (source / functions) Coverage Total Hit
Test: SHA:b879ecb8e99e175eea0a293a888bda853da2b19c Lines: 0.0 % 46 0
Test Date: 2025-01-17 19:00:11 Functions: 0.0 % 12 0

            Line data    Source code
       1              : /*
       2              :  *
       3              :  *    Copyright (c) 2021 Project CHIP Authors
       4              :  *    All rights reserved.
       5              :  *
       6              :  *    Licensed under the Apache License, Version 2.0 (the "License");
       7              :  *    you may not use this file except in compliance with the License.
       8              :  *    You may obtain a copy of the License at
       9              :  *
      10              :  *        http://www.apache.org/licenses/LICENSE-2.0
      11              :  *
      12              :  *    Unless required by applicable law or agreed to in writing, software
      13              :  *    distributed under the License is distributed on an "AS IS" BASIS,
      14              :  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      15              :  *    See the License for the specific language governing permissions and
      16              :  *    limitations under the License.
      17              :  */
      18              : 
      19              : #pragma once
      20              : 
      21              : #include <app/AppConfig.h>
      22              : #include <app/AttributePathParams.h>
      23              : #include <app/InteractionModelEngine.h>
      24              : #include <app/ReadClient.h>
      25              : #include <app/ReadPrepareParams.h>
      26              : #include <controller/TypedReadCallback.h>
      27              : 
      28              : #if CHIP_CONFIG_ENABLE_READ_CLIENT
      29              : namespace chip {
      30              : namespace Controller {
      31              : namespace detail {
      32              : 
      33              : using SubscriptionOnDoneCallback = std::function<void(void)>;
      34              : 
      35              : template <typename DecodableAttributeType>
      36              : struct ReportAttributeParams : public app::ReadPrepareParams
      37              : {
      38            0 :     ReportAttributeParams(const SessionHandle & sessionHandle) : app::ReadPrepareParams(sessionHandle)
      39              :     {
      40            0 :         mKeepSubscriptions = false;
      41            0 :     }
      42              :     typename TypedReadAttributeCallback<DecodableAttributeType>::OnSuccessCallbackType mOnReportCb;
      43              :     typename TypedReadAttributeCallback<DecodableAttributeType>::OnErrorCallbackType mOnErrorCb;
      44              :     typename TypedReadAttributeCallback<DecodableAttributeType>::OnSubscriptionEstablishedCallbackType
      45              :         mOnSubscriptionEstablishedCb = nullptr;
      46              :     typename TypedReadAttributeCallback<DecodableAttributeType>::OnResubscriptionAttemptCallbackType mOnResubscriptionAttemptCb =
      47              :         nullptr;
      48              :     SubscriptionOnDoneCallback mOnDoneCb         = nullptr;
      49              :     app::ReadClient::InteractionType mReportType = app::ReadClient::InteractionType::Read;
      50              : };
      51              : 
      52              : template <typename DecodableAttributeType>
      53            0 : CHIP_ERROR ReportAttribute(Messaging::ExchangeManager * exchangeMgr, EndpointId endpointId, ClusterId clusterId,
      54              :                            AttributeId attributeId, ReportAttributeParams<DecodableAttributeType> && readParams,
      55              :                            const Optional<DataVersion> & aDataVersion = NullOptional)
      56              : {
      57            0 :     app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance();
      58            0 :     CHIP_ERROR err                       = CHIP_NO_ERROR;
      59              : 
      60            0 :     auto readPaths = Platform::MakeUnique<app::AttributePathParams>(endpointId, clusterId, attributeId);
      61            0 :     VerifyOrReturnError(readPaths != nullptr, CHIP_ERROR_NO_MEMORY);
      62            0 :     readParams.mpAttributePathParamsList    = readPaths.get();
      63            0 :     readParams.mAttributePathParamsListSize = 1;
      64            0 :     chip::Platform::UniquePtr<chip::app::DataVersionFilter> dataVersionFilters;
      65            0 :     if (aDataVersion.HasValue())
      66              :     {
      67            0 :         dataVersionFilters = Platform::MakeUnique<app::DataVersionFilter>(endpointId, clusterId, aDataVersion.Value());
      68            0 :         VerifyOrReturnError(dataVersionFilters != nullptr, CHIP_ERROR_NO_MEMORY);
      69            0 :         readParams.mpDataVersionFilterList    = dataVersionFilters.get();
      70            0 :         readParams.mDataVersionFilterListSize = 1;
      71              :     }
      72            0 :     auto onDoneCb = readParams.mOnDoneCb;
      73            0 :     auto onDone   = [onDoneCb](TypedReadAttributeCallback<DecodableAttributeType> * callback) {
      74            0 :         if (onDoneCb)
      75              :         {
      76            0 :             onDoneCb();
      77              :         }
      78            0 :         chip::Platform::Delete(callback);
      79              :     };
      80              : 
      81            0 :     auto callback = chip::Platform::MakeUnique<TypedReadAttributeCallback<DecodableAttributeType>>(
      82            0 :         clusterId, attributeId, readParams.mOnReportCb, readParams.mOnErrorCb, onDone, readParams.mOnSubscriptionEstablishedCb,
      83            0 :         readParams.mOnResubscriptionAttemptCb);
      84            0 :     VerifyOrReturnError(callback != nullptr, CHIP_ERROR_NO_MEMORY);
      85              : 
      86            0 :     auto readClient =
      87            0 :         chip::Platform::MakeUnique<app::ReadClient>(engine, exchangeMgr, callback->GetBufferedCallback(), readParams.mReportType);
      88            0 :     VerifyOrReturnError(readClient != nullptr, CHIP_ERROR_NO_MEMORY);
      89              : 
      90            0 :     if (readClient->IsSubscriptionType())
      91              :     {
      92            0 :         readPaths.release();
      93            0 :         dataVersionFilters.release();
      94              : 
      95            0 :         err = readClient->SendAutoResubscribeRequest(std::move(readParams));
      96            0 :         ReturnErrorOnFailure(err);
      97              :     }
      98              :     else
      99              :     {
     100            0 :         err = readClient->SendRequest(readParams);
     101            0 :         ReturnErrorOnFailure(err);
     102              :     }
     103              : 
     104              :     //
     105              :     // At this point, we'll get a callback through the OnDone callback above regardless of success or failure
     106              :     // of the read operation to permit us to free up the callback object. So, release ownership of the callback
     107              :     // object now to prevent it from being reclaimed at the end of this scoped block.
     108              :     //
     109            0 :     callback->AdoptReadClient(std::move(readClient));
     110            0 :     callback.release();
     111              : 
     112            0 :     return err;
     113            0 : }
     114              : 
     115              : } // namespace detail
     116              : 
     117              : /**
     118              :  * To avoid instantiating all the complicated read code on a per-attribute
     119              :  * basis, we have a helper that's just templated on the type.
     120              :  */
     121              : template <typename DecodableAttributeType>
     122            0 : CHIP_ERROR ReadAttribute(Messaging::ExchangeManager * exchangeMgr, const SessionHandle & sessionHandle, EndpointId endpointId,
     123              :                          ClusterId clusterId, AttributeId attributeId,
     124              :                          typename TypedReadAttributeCallback<DecodableAttributeType>::OnSuccessCallbackType onSuccessCb,
     125              :                          typename TypedReadAttributeCallback<DecodableAttributeType>::OnErrorCallbackType onErrorCb,
     126              :                          bool fabricFiltered = true)
     127              : {
     128            0 :     detail::ReportAttributeParams<DecodableAttributeType> params(sessionHandle);
     129            0 :     params.mOnReportCb       = onSuccessCb;
     130            0 :     params.mOnErrorCb        = onErrorCb;
     131            0 :     params.mIsFabricFiltered = fabricFiltered;
     132            0 :     return detail::ReportAttribute(exchangeMgr, endpointId, clusterId, attributeId, std::move(params), NullOptional);
     133            0 : }
     134              : 
     135              : /*
     136              :  * A typed read attribute function that takes as input a template parameter that encapsulates the type information
     137              :  * for a given attribute as well as callbacks for success and failure and either returns a decoded cluster-object representation
     138              :  * of the requested attribute through the provided success callback or calls the provided failure callback.
     139              :  *
     140              :  * The AttributeTypeInfo is generally expected to be a ClusterName::Attributes::AttributeName::TypeInfo struct, but any
     141              :  * object that contains type information exposed through a 'DecodableType' type declaration as well as GetClusterId() and
     142              :  * GetAttributeId() methods is expected to work.
     143              :  */
     144              : template <typename AttributeTypeInfo>
     145              : CHIP_ERROR
     146              : ReadAttribute(Messaging::ExchangeManager * exchangeMgr, const SessionHandle & sessionHandle, EndpointId endpointId,
     147              :               typename TypedReadAttributeCallback<typename AttributeTypeInfo::DecodableType>::OnSuccessCallbackType onSuccessCb,
     148              :               typename TypedReadAttributeCallback<typename AttributeTypeInfo::DecodableType>::OnErrorCallbackType onErrorCb,
     149              :               bool fabricFiltered = true)
     150              : {
     151              :     return ReadAttribute<typename AttributeTypeInfo::DecodableType>(
     152              :         exchangeMgr, sessionHandle, endpointId, AttributeTypeInfo::GetClusterId(), AttributeTypeInfo::GetAttributeId(), onSuccessCb,
     153              :         onErrorCb, fabricFiltered);
     154              : }
     155              : 
     156              : // Helper for SubscribeAttribute to reduce the amount of code generated.
     157              : template <typename DecodableAttributeType>
     158              : CHIP_ERROR SubscribeAttribute(
     159              :     Messaging::ExchangeManager * exchangeMgr, const SessionHandle & sessionHandle, EndpointId endpointId, ClusterId clusterId,
     160              :     AttributeId attributeId, typename TypedReadAttributeCallback<DecodableAttributeType>::OnSuccessCallbackType onReportCb,
     161              :     typename TypedReadAttributeCallback<DecodableAttributeType>::OnErrorCallbackType onErrorCb, uint16_t minIntervalFloorSeconds,
     162              :     uint16_t maxIntervalCeilingSeconds,
     163              :     typename TypedReadAttributeCallback<DecodableAttributeType>::OnSubscriptionEstablishedCallbackType onSubscriptionEstablishedCb =
     164              :         nullptr,
     165              :     typename TypedReadAttributeCallback<DecodableAttributeType>::OnResubscriptionAttemptCallbackType onResubscriptionAttemptCb =
     166              :         nullptr,
     167              :     bool fabricFiltered = true, bool keepPreviousSubscriptions = false, const Optional<DataVersion> & aDataVersion = NullOptional,
     168              :     typename detail::SubscriptionOnDoneCallback onDoneCb = nullptr)
     169              : {
     170              :     detail::ReportAttributeParams<DecodableAttributeType> params(sessionHandle);
     171              :     params.mOnReportCb                  = onReportCb;
     172              :     params.mOnErrorCb                   = onErrorCb;
     173              :     params.mOnSubscriptionEstablishedCb = onSubscriptionEstablishedCb;
     174              :     params.mOnResubscriptionAttemptCb   = onResubscriptionAttemptCb;
     175              :     params.mOnDoneCb                    = onDoneCb;
     176              :     params.mMinIntervalFloorSeconds     = minIntervalFloorSeconds;
     177              :     params.mMaxIntervalCeilingSeconds   = maxIntervalCeilingSeconds;
     178              :     params.mKeepSubscriptions           = keepPreviousSubscriptions;
     179              :     params.mReportType                  = app::ReadClient::InteractionType::Subscribe;
     180              :     params.mIsFabricFiltered            = fabricFiltered;
     181              :     return detail::ReportAttribute(exchangeMgr, endpointId, clusterId, attributeId, std::move(params), aDataVersion);
     182              : }
     183              : 
     184              : /*
     185              :  * A typed way to subscribe to the value of a single attribute.  See
     186              :  * documentation for ReadAttribute above for details on how AttributeTypeInfo
     187              :  * works.
     188              :  *
     189              :  * A const view-only reference to the underlying ReadClient is passed in through the OnSubscriptionEstablishedCallbackType
     190              :  * argument. This reference is valid until the error callback is invoked at which point, this reference is no longer valid
     191              :  * and should not be used any more.
     192              :  */
     193              : template <typename AttributeTypeInfo>
     194              : CHIP_ERROR SubscribeAttribute(
     195              :     Messaging::ExchangeManager * exchangeMgr, const SessionHandle & sessionHandle, EndpointId endpointId,
     196              :     typename TypedReadAttributeCallback<typename AttributeTypeInfo::DecodableType>::OnSuccessCallbackType onReportCb,
     197              :     typename TypedReadAttributeCallback<typename AttributeTypeInfo::DecodableType>::OnErrorCallbackType onErrorCb,
     198              :     uint16_t aMinIntervalFloorSeconds, uint16_t aMaxIntervalCeilingSeconds,
     199              :     typename TypedReadAttributeCallback<typename AttributeTypeInfo::DecodableType>::OnSubscriptionEstablishedCallbackType
     200              :         onSubscriptionEstablishedCb = nullptr,
     201              :     typename TypedReadAttributeCallback<typename AttributeTypeInfo::DecodableType>::OnResubscriptionAttemptCallbackType
     202              :         onResubscriptionAttemptCb = nullptr,
     203              :     bool fabricFiltered = true, bool keepPreviousSubscriptions = false, const Optional<DataVersion> & aDataVersion = NullOptional,
     204              :     typename detail::SubscriptionOnDoneCallback onDoneCb = nullptr)
     205              : {
     206              :     return SubscribeAttribute<typename AttributeTypeInfo::DecodableType>(
     207              :         exchangeMgr, sessionHandle, endpointId, AttributeTypeInfo::GetClusterId(), AttributeTypeInfo::GetAttributeId(), onReportCb,
     208              :         onErrorCb, aMinIntervalFloorSeconds, aMaxIntervalCeilingSeconds, onSubscriptionEstablishedCb, onResubscriptionAttemptCb,
     209              :         fabricFiltered, keepPreviousSubscriptions, aDataVersion, onDoneCb);
     210              : }
     211              : 
     212              : namespace detail {
     213              : 
     214              : template <typename DecodableEventType>
     215              : struct ReportEventParams : public app::ReadPrepareParams
     216              : {
     217              :     ReportEventParams(const SessionHandle & sessionHandle) : app::ReadPrepareParams(sessionHandle) {}
     218              :     typename TypedReadEventCallback<DecodableEventType>::OnSuccessCallbackType mOnReportCb;
     219              :     typename TypedReadEventCallback<DecodableEventType>::OnErrorCallbackType mOnErrorCb;
     220              :     typename TypedReadEventCallback<DecodableEventType>::OnDoneCallbackType mOnDoneCb;
     221              :     typename TypedReadEventCallback<DecodableEventType>::OnSubscriptionEstablishedCallbackType mOnSubscriptionEstablishedCb =
     222              :         nullptr;
     223              :     typename TypedReadEventCallback<DecodableEventType>::OnResubscriptionAttemptCallbackType mOnResubscriptionAttemptCb = nullptr;
     224              :     app::ReadClient::InteractionType mReportType = app::ReadClient::InteractionType::Read;
     225              : };
     226              : 
     227              : template <typename DecodableEventType>
     228              : CHIP_ERROR ReportEvent(Messaging::ExchangeManager * apExchangeMgr, EndpointId endpointId,
     229              :                        ReportEventParams<DecodableEventType> && readParams, bool aIsUrgentEvent)
     230              : {
     231              :     ClusterId clusterId                  = DecodableEventType::GetClusterId();
     232              :     EventId eventId                      = DecodableEventType::GetEventId();
     233              :     app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance();
     234              :     CHIP_ERROR err                       = CHIP_NO_ERROR;
     235              : 
     236              :     auto readPaths = Platform::MakeUnique<app::EventPathParams>(endpointId, clusterId, eventId, aIsUrgentEvent);
     237              :     VerifyOrReturnError(readPaths != nullptr, CHIP_ERROR_NO_MEMORY);
     238              : 
     239              :     readParams.mpEventPathParamsList = readPaths.get();
     240              : 
     241              :     readParams.mEventPathParamsListSize = 1;
     242              : 
     243              :     auto callback = chip::Platform::MakeUnique<TypedReadEventCallback<DecodableEventType>>(
     244              :         readParams.mOnReportCb, readParams.mOnErrorCb, readParams.mOnDoneCb, readParams.mOnSubscriptionEstablishedCb,
     245              :         readParams.mOnResubscriptionAttemptCb);
     246              : 
     247              :     VerifyOrReturnError(callback != nullptr, CHIP_ERROR_NO_MEMORY);
     248              : 
     249              :     auto readClient = chip::Platform::MakeUnique<app::ReadClient>(engine, apExchangeMgr, *callback.get(), readParams.mReportType);
     250              :     VerifyOrReturnError(readClient != nullptr, CHIP_ERROR_NO_MEMORY);
     251              : 
     252              :     if (readClient->IsSubscriptionType())
     253              :     {
     254              :         readPaths.release();
     255              :         err = readClient->SendAutoResubscribeRequest(std::move(readParams));
     256              :         ReturnErrorOnFailure(err);
     257              :     }
     258              :     else
     259              :     {
     260              :         err = readClient->SendRequest(readParams);
     261              :         ReturnErrorOnFailure(err);
     262              :     }
     263              : 
     264              :     //
     265              :     // At this point, we'll get a callback through the OnDone callback above regardless of success or failure
     266              :     // of the read operation to permit us to free up the callback object. So, release ownership of the callback
     267              :     // object now to prevent it from being reclaimed at the end of this scoped block.
     268              :     //
     269              :     callback->AdoptReadClient(std::move(readClient));
     270              :     callback.release();
     271              : 
     272              :     return err;
     273              : }
     274              : 
     275              : } // namespace detail
     276              : 
     277              : /*
     278              :  * A typed read event function that takes as input a template parameter that encapsulates the type information
     279              :  * for a given attribute as well as callbacks for success and failure and either returns a decoded cluster-object representation
     280              :  * of the requested attribute through the provided success callback or calls the provided failure callback.
     281              :  *
     282              :  * The DecodableEventType is generally expected to be a ClusterName::Events::EventName::DecodableEventType struct, but any
     283              :  * object that contains type information exposed through a 'DecodableType' type declaration as well as GetClusterId() and
     284              :  * GetEventId() methods is expected to work.
     285              :  *
     286              :  * @param[in] onSuccessCb Used to deliver event data received through the Read interactions
     287              :  * @param[in] onErrorCb failureCb will be called when an error occurs *after* a successful call to ReadEvent.
     288              :  * @param[in] onDoneCb    OnDone will be called when ReadClient has finished all work for event retrieval, it is possible that there
     289              :  * is no event.
     290              :  */
     291              : template <typename DecodableEventType>
     292              : CHIP_ERROR ReadEvent(Messaging::ExchangeManager * exchangeMgr, const SessionHandle & sessionHandle, EndpointId endpointId,
     293              :                      typename TypedReadEventCallback<DecodableEventType>::OnSuccessCallbackType onSuccessCb,
     294              :                      typename TypedReadEventCallback<DecodableEventType>::OnErrorCallbackType onErrorCb,
     295              :                      typename TypedReadEventCallback<DecodableEventType>::OnDoneCallbackType onDoneCb)
     296              : {
     297              :     detail::ReportEventParams<DecodableEventType> params(sessionHandle);
     298              :     params.mOnReportCb = onSuccessCb;
     299              :     params.mOnErrorCb  = onErrorCb;
     300              :     params.mOnDoneCb   = onDoneCb;
     301              :     return detail::ReportEvent(exchangeMgr, endpointId, std::move(params), false /*aIsUrgentEvent*/);
     302              : }
     303              : 
     304              : /**
     305              :  * A functon that allows subscribing to one particular event.  This works
     306              :  * similarly to ReadEvent but keeps reporting events as they are emitted.
     307              :  */
     308              : template <typename DecodableEventType>
     309              : CHIP_ERROR SubscribeEvent(
     310              :     Messaging::ExchangeManager * exchangeMgr, const SessionHandle & sessionHandle, EndpointId endpointId,
     311              :     typename TypedReadEventCallback<DecodableEventType>::OnSuccessCallbackType onReportCb,
     312              :     typename TypedReadEventCallback<DecodableEventType>::OnErrorCallbackType onErrorCb, uint16_t minIntervalFloorSeconds,
     313              :     uint16_t maxIntervalCeilingSeconds,
     314              :     typename TypedReadEventCallback<DecodableEventType>::OnSubscriptionEstablishedCallbackType onSubscriptionEstablishedCb =
     315              :         nullptr,
     316              :     typename TypedReadEventCallback<DecodableEventType>::OnResubscriptionAttemptCallbackType onResubscriptionAttemptCb = nullptr,
     317              :     bool keepPreviousSubscriptions = false, bool aIsUrgentEvent = false)
     318              : {
     319              :     detail::ReportEventParams<DecodableEventType> params(sessionHandle);
     320              :     params.mOnReportCb                  = onReportCb;
     321              :     params.mOnErrorCb                   = onErrorCb;
     322              :     params.mOnDoneCb                    = nullptr;
     323              :     params.mOnSubscriptionEstablishedCb = onSubscriptionEstablishedCb;
     324              :     params.mOnResubscriptionAttemptCb   = onResubscriptionAttemptCb;
     325              :     params.mMinIntervalFloorSeconds     = minIntervalFloorSeconds;
     326              :     params.mMaxIntervalCeilingSeconds   = maxIntervalCeilingSeconds;
     327              :     params.mKeepSubscriptions           = keepPreviousSubscriptions;
     328              :     params.mReportType                  = app::ReadClient::InteractionType::Subscribe;
     329              :     return detail::ReportEvent(exchangeMgr, endpointId, std::move(params), aIsUrgentEvent);
     330              : }
     331              : 
     332              : } // namespace Controller
     333              : } // namespace chip
     334              : #endif // CHIP_CONFIG_ENABLE_READ_CLIENT
        

Generated by: LCOV version 2.0-1