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

Generated by: LCOV version 1.14