Skip to content

Commit

Permalink
Add an API to subscribe to a single event. (#12860)
Browse files Browse the repository at this point in the history
Might be useful in YAML tests.
  • Loading branch information
bzbarsky-apple authored and pull[bot] committed Dec 11, 2021
1 parent dfcb8a4 commit 4608323
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 22 deletions.
87 changes: 67 additions & 20 deletions src/controller/ReadInteraction.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ namespace Controller {
namespace detail {

template <typename DecodableAttributeType>
struct ReportParams : public app::ReadPrepareParams
struct ReportAttributeParams : public app::ReadPrepareParams
{
ReportParams(SessionHandle sessionHandle) : app::ReadPrepareParams(sessionHandle) { mKeepSubscriptions = false; }
ReportAttributeParams(SessionHandle sessionHandle) : app::ReadPrepareParams(sessionHandle) { mKeepSubscriptions = false; }
typename TypedReadAttributeCallback<DecodableAttributeType>::OnSuccessCallbackType mOnReportCb;
typename TypedReadAttributeCallback<DecodableAttributeType>::OnErrorCallbackType mOnErrorCb;
typename TypedReadAttributeCallback<DecodableAttributeType>::OnSubscriptionEstablishedCallbackType
Expand All @@ -40,7 +40,7 @@ struct ReportParams : public app::ReadPrepareParams

template <typename DecodableAttributeType>
CHIP_ERROR ReportAttribute(Messaging::ExchangeManager * exchangeMgr, EndpointId endpointId, ClusterId clusterId,
AttributeId attributeId, ReportParams<DecodableAttributeType> && readParams)
AttributeId attributeId, ReportAttributeParams<DecodableAttributeType> && readParams)
{
app::AttributePathParams attributePath(endpointId, clusterId, attributeId);
app::ReadClient * readClient = nullptr;
Expand Down Expand Up @@ -89,7 +89,7 @@ CHIP_ERROR ReadAttribute(Messaging::ExchangeManager * exchangeMgr, const Session
typename TypedReadAttributeCallback<DecodableAttributeType>::OnSuccessCallbackType onSuccessCb,
typename TypedReadAttributeCallback<DecodableAttributeType>::OnErrorCallbackType onErrorCb)
{
detail::ReportParams<DecodableAttributeType> params(sessionHandle);
detail::ReportAttributeParams<DecodableAttributeType> params(sessionHandle);
params.mOnReportCb = onSuccessCb;
params.mOnErrorCb = onErrorCb;
return detail::ReportAttribute(exchangeMgr, endpointId, clusterId, attributeId, std::move(params));
Expand Down Expand Up @@ -125,7 +125,7 @@ CHIP_ERROR SubscribeAttribute(Messaging::ExchangeManager * exchangeMgr, const Se
typename TypedReadAttributeCallback<DecodableAttributeType>::OnSubscriptionEstablishedCallbackType
onSubscriptionEstablishedCb = nullptr)
{
detail::ReportParams<DecodableAttributeType> params(sessionHandle);
detail::ReportAttributeParams<DecodableAttributeType> params(sessionHandle);
params.mOnReportCb = onReportCb;
params.mOnErrorCb = onErrorCb;
params.mOnSubscriptionEstablishedCb = onSubscriptionEstablishedCb;
Expand Down Expand Up @@ -154,24 +154,26 @@ CHIP_ERROR SubscribeAttribute(
onErrorCb, aMinIntervalFloorSeconds, aMaxIntervalCeilingSeconds, onSubscriptionEstablishedCb);
}

/*
* A typed read event function that takes as input a template parameter that encapsulates the type information
* for a given attribute as well as callbacks for success and failure and either returns a decoded cluster-object representation
* of the requested attribute through the provided success callback or calls the provided failure callback.
*
* The DecodableEventType is generally expected to be a ClusterName::Events::EventName::DecodableEventType struct, but any
* object that contains type information exposed through a 'DecodableType' type declaration as well as GetClusterId() and
* GetEventId() methods is expected to work.
*/
namespace detail {

template <typename DecodableEventType>
CHIP_ERROR ReadEvent(Messaging::ExchangeManager * apExchangeMgr, const SessionHandle sessionHandle, EndpointId endpointId,
typename TypedReadEventCallback<DecodableEventType>::OnSuccessCallbackType onSuccessCb,
typename TypedReadEventCallback<DecodableEventType>::OnErrorCallbackType onErrorCb)
struct ReportEventParams : public app::ReadPrepareParams
{
ReportEventParams(SessionHandle sessionHandle) : app::ReadPrepareParams(sessionHandle) { mKeepSubscriptions = false; }
typename TypedReadEventCallback<DecodableEventType>::OnSuccessCallbackType mOnReportCb;
typename TypedReadEventCallback<DecodableEventType>::OnErrorCallbackType mOnErrorCb;
typename TypedReadEventCallback<DecodableEventType>::OnSubscriptionEstablishedCallbackType mOnSubscriptionEstablishedCb =
nullptr;
app::ReadClient::InteractionType mReportType = app::ReadClient::InteractionType::Read;
};

template <typename DecodableEventType>
CHIP_ERROR ReportEvent(Messaging::ExchangeManager * apExchangeMgr, EndpointId endpointId,
ReportEventParams<DecodableEventType> && readParams)
{
ClusterId clusterId = DecodableEventType::GetClusterId();
EventId eventId = DecodableEventType::GetEventId();
app::EventPathParams eventPath(endpointId, clusterId, eventId);
app::ReadPrepareParams readParams(sessionHandle);
app::ReadClient * readClient = nullptr;
app::InteractionModelEngine * engine = app::InteractionModelEngine::GetInstance();
CHIP_ERROR err = CHIP_NO_ERROR;
Expand All @@ -183,11 +185,12 @@ CHIP_ERROR ReadEvent(Messaging::ExchangeManager * apExchangeMgr, const SessionHa
chip::Platform::Delete(callback);
};

auto callback = chip::Platform::MakeUnique<TypedReadEventCallback<DecodableEventType>>(onSuccessCb, onErrorCb, onDone);
auto callback = chip::Platform::MakeUnique<TypedReadEventCallback<DecodableEventType>>(
readParams.mOnReportCb, readParams.mOnErrorCb, onDone, readParams.mOnSubscriptionEstablishedCb);

VerifyOrReturnError(callback != nullptr, CHIP_ERROR_NO_MEMORY);

ReturnErrorOnFailure(engine->NewReadClient(&readClient, app::ReadClient::InteractionType::Read, callback.get()));
ReturnErrorOnFailure(engine->NewReadClient(&readClient, readParams.mReportType, callback.get()));

err = readClient->SendRequest(readParams);
if (err != CHIP_NO_ERROR)
Expand All @@ -205,5 +208,49 @@ CHIP_ERROR ReadEvent(Messaging::ExchangeManager * apExchangeMgr, const SessionHa
return err;
}

} // namespace detail

/*
* A typed read event function that takes as input a template parameter that encapsulates the type information
* for a given attribute as well as callbacks for success and failure and either returns a decoded cluster-object representation
* of the requested attribute through the provided success callback or calls the provided failure callback.
*
* The DecodableEventType is generally expected to be a ClusterName::Events::EventName::DecodableEventType struct, but any
* object that contains type information exposed through a 'DecodableType' type declaration as well as GetClusterId() and
* GetEventId() methods is expected to work.
*/
template <typename DecodableEventType>
CHIP_ERROR ReadEvent(Messaging::ExchangeManager * exchangeMgr, const SessionHandle sessionHandle, EndpointId endpointId,
typename TypedReadEventCallback<DecodableEventType>::OnSuccessCallbackType onSuccessCb,
typename TypedReadEventCallback<DecodableEventType>::OnErrorCallbackType onErrorCb)
{
detail::ReportEventParams<DecodableEventType> params(sessionHandle);
params.mOnReportCb = onSuccessCb;
params.mOnErrorCb = onErrorCb;
return detail::ReportEvent(exchangeMgr, endpointId, std::move(params));
}

/**
* A functon that allows subscribing to one particular event. This works
* similarly to ReadEvent but keeps reporting events as they are emitted.
*/
template <typename DecodableEventType>
CHIP_ERROR SubscribeEvent(Messaging::ExchangeManager * exchangeMgr, const SessionHandle sessionHandle, EndpointId endpointId,
typename TypedReadEventCallback<DecodableEventType>::OnSuccessCallbackType onReportCb,
typename TypedReadEventCallback<DecodableEventType>::OnErrorCallbackType onErrorCb,
uint16_t minIntervalFloorSeconds, uint16_t maxIntervalCeilingSeconds,
typename TypedReadEventCallback<DecodableEventType>::OnSubscriptionEstablishedCallbackType
onSubscriptionEstablishedCb = nullptr)
{
detail::ReportEventParams<DecodableEventType> params(sessionHandle);
params.mOnReportCb = onReportCb;
params.mOnErrorCb = onErrorCb;
params.mOnSubscriptionEstablishedCb = onSubscriptionEstablishedCb;
params.mMinIntervalFloorSeconds = minIntervalFloorSeconds;
params.mMaxIntervalCeilingSeconds = maxIntervalCeilingSeconds;
params.mReportType = app::ReadClient::InteractionType::Subscribe;
return detail::ReportEvent(exchangeMgr, endpointId, std::move(params));
}

} // namespace Controller
} // namespace chip
16 changes: 14 additions & 2 deletions src/controller/TypedReadCallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,12 @@ class TypedReadEventCallback final : public app::ReadClient::Callback
using OnErrorCallbackType = std::function<void(const app::EventHeader * apEventHeader,
Protocols::InteractionModel::Status aIMStatus, CHIP_ERROR aError)>;
using OnDoneCallbackType = std::function<void(app::ReadClient * client, TypedReadEventCallback * callback)>;
using OnSubscriptionEstablishedCallbackType = std::function<void()>;

TypedReadEventCallback(OnSuccessCallbackType aOnSuccess, OnErrorCallbackType aOnError, OnDoneCallbackType aOnDone) :
mOnSuccess(aOnSuccess), mOnError(aOnError), mOnDone(aOnDone)
TypedReadEventCallback(OnSuccessCallbackType aOnSuccess, OnErrorCallbackType aOnError, OnDoneCallbackType aOnDone,
OnSubscriptionEstablishedCallbackType aOnSubscriptionEstablished = nullptr) :
mOnSuccess(aOnSuccess),
mOnError(aOnError), mOnDone(aOnDone), mOnSubscriptionEstablished(aOnSubscriptionEstablished)
{}

private:
Expand Down Expand Up @@ -162,9 +165,18 @@ class TypedReadEventCallback final : public app::ReadClient::Callback

void OnDone(app::ReadClient * apReadClient) override { mOnDone(apReadClient, this); }

void OnSubscriptionEstablished(const app::ReadClient * apReadClient) override
{
if (mOnSubscriptionEstablished)
{
mOnSubscriptionEstablished();
}
}

OnSuccessCallbackType mOnSuccess;
OnErrorCallbackType mOnError;
OnDoneCallbackType mOnDone;
OnSubscriptionEstablishedCallbackType mOnSubscriptionEstablished;
};

} // namespace Controller
Expand Down

0 comments on commit 4608323

Please sign in to comment.