Skip to content

Commit

Permalink
Add IM/Ember Read/Writer Interface and attribute read for IM
Browse files Browse the repository at this point in the history
Summary of Changes:
-- Add initial IM read attribute implementation and ember read/write
interface so that read client can send IM read request with attribute
path,  interaction model engine receive this request and ask
reporting engine generate the corresponding interested attributes and
send it back via read hander.

-- Add unit and cirque integration test
  • Loading branch information
yunhanw-google committed Apr 21, 2021
1 parent 0e9ec10 commit 6fa241b
Show file tree
Hide file tree
Showing 14 changed files with 464 additions and 19 deletions.
10 changes: 1 addition & 9 deletions src/app/AttributePathParams.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,7 @@ struct AttributePathParams
mNodeId(aNodeId),
mEndpointId(aEndpointId), mClusterId(aClusterId), mFieldId(aFieldId), mListIndex(aListIndex), mFlags(aFlags)
{}
AttributePathParams(const AttributePathParams & aAttributePathParams)
{
mNodeId = aAttributePathParams.mNodeId;
mEndpointId = aAttributePathParams.mEndpointId;
mClusterId = aAttributePathParams.mClusterId;
mFieldId = aAttributePathParams.mFieldId;
mListIndex = aAttributePathParams.mListIndex;
mFlags = aAttributePathParams.mFlags;
}
AttributePathParams(){};
bool IsSamePath(const AttributePathParams & other) const
{
if (other.mNodeId != mNodeId || other.mEndpointId != mEndpointId || other.mClusterId != mClusterId)
Expand Down
1 change: 1 addition & 0 deletions src/app/ClusterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ struct ClusterInfo
ClusterInfo(const AttributePathParams & aAttributePathParams, bool aDirty) :
mAttributePathParams(aAttributePathParams), mDirty(aDirty)
{}
ClusterInfo() {}
bool IsDirty() { return mDirty; }
void SetDirty() { mDirty = true; }
void ClearDirty() { mDirty = false; }
Expand Down
90 changes: 90 additions & 0 deletions src/app/InteractionModelEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,60 @@ void InteractionModelEngine::OnResponseTimeout(Messaging::ExchangeContext * ec)
ChipLogProgress(DataManagement, "Time out! failed to receive echo response from Exchange: %d", ec->GetExchangeId());
}


void InteractionModelEngine::ReleaseClusterInfoListToPool(ReadHandler * const apReadHandler)
{
ClusterInfo * const clusterInfoList = apReadHandler->GetClusterInfoList();
size_t numClusterInfos = apReadHandler->GetNumClusterInfos();
size_t numClusterInfosToBeAffected;

apReadHandler->ClearClusterInfo();

if (numClusterInfos == 0)
{
ChipLogDetail(DataManagement, "No cluster instances allocated");
ExitNow();
}

// make sure everything is still sane
ChipLogIfFalse(clusterInfoList >= mClusterInfoPool);
ChipLogIfFalse(numClusterInfos <= mNumClusterInfos);

// mPathGroupPool + IM_PUBLISHER_MAX_NUM_PATH_GROUPS is a pointer which points to the last+1byte of this array
// clusterInfoList is a pointer to the first cluster instance to be released
// the result of subtraction is the number of cluster instances from clusterInfoList to the end of this array
numClusterInfosToBeAffected = ((size_t) mClusterInfoPool + mNumClusterInfos) - (size_t) clusterInfoList;

// Shrink the clusterInfosInPool by the number of cluster instances.
mNumClusterInfos -= numClusterInfos;

ChipLogDetail(DataManagement, "numClusterInfos is %d, and numClusterInfosToBeAffected is %d", numClusterInfos,
numClusterInfosToBeAffected);
if (numClusterInfos == numClusterInfosToBeAffected)
{
ChipLogDetail(DataManagement, "Releasing the last block of cluster instances");
ExitNow();
}

ChipLogDetail(DataManagement, "Moving %d cluster infos forward", numClusterInfosToBeAffected - numClusterInfos);

memmove(clusterInfoList, clusterInfoList + numClusterInfos,
sizeof(ClusterInfo) * (numClusterInfosToBeAffected - numClusterInfos));

for (size_t i = 0; i < CHIP_MAX_NUM_READ_HANDLER; ++i)
{
ReadHandler * const handler = mReadHandlers + i;

if ((apReadHandler != handler) && (handler->GetClusterInfoList() > clusterInfoList))
{
handler->ShrinkClusterInfo(numClusterInfos);
}
}

exit:
ChipLogDetail(DataManagement, "Number of allocated cluster instances: %u", mNumClusterInfos);
}

// The default implementation to make compiler happy before codegen for this is ready.
// TODO: Remove this after codegen is ready.
void __attribute__((weak))
Expand All @@ -240,9 +294,45 @@ DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aComman
"Default DispatchSingleClusterCommand is called, this should be replaced by actual dispatched for cluster commands");
}

CHIP_ERROR __attribute__((weak))
ReadSingleClusterData(NodeId aNodeId, ClusterId aClusterId, EndpointId aEndPointId, FieldId aFieldId,
TLV::TLVWriter & aWriter)
{
ChipLogDetail(DataManagement, "Received Cluster Command: Cluster=%" PRIx16 " NodeId=%" PRIx64 " Endpoint=%" PRIx8" FieldId=%" PRIx8, aClusterId,
aNodeId, aEndPointId, aFieldId);
ChipLogError(
DataManagement,
"Default ReadSingleClusterData is called, this should be replaced by actual dispatched for cluster");
return CHIP_NO_ERROR;
}

CHIP_ERROR __attribute__((weak))
WriteSingleClusterData(NodeId aNodeId, ClusterId aClusterId, EndpointId aEndPointId, FieldId aFieldId,
TLV::TLVReader & aReader)
{
ChipLogDetail(DataManagement, "Received Cluster Command: Cluster=%" PRIx16 " NodeId=%" PRIx64 " Endpoint=%" PRIx8" FieldId=%" PRIx8, aClusterId,
aNodeId, aEndPointId, aFieldId);
ChipLogError(
DataManagement,
"Default WriteSingleClusterData is called, this should be replaced by actual dispatched for cluster");
return CHIP_NO_ERROR;
}

uint16_t InteractionModelEngine::GetReadClientArrayIndex(const ReadClient * const apReadClient) const
{
return static_cast<uint16_t>(apReadClient - mReadClients);
}

CHIP_ERROR InteractionModelEngine::GetFirstAvailableClusterInfo(ClusterInfo *& apClusterInfo)
{
if (mNumClusterInfos >= IM_SERVER_MAX_NUM_PATH_GROUPS)
{
return CHIP_ERROR_NO_MEMORY;
}
apClusterInfo = &mClusterInfoPool[mNumClusterInfos];
mNumClusterInfos ++;
apClusterInfo->ClearDirty();
return CHIP_NO_ERROR;
}
} // namespace app
} // namespace chip
13 changes: 12 additions & 1 deletion src/app/InteractionModelEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,12 +44,15 @@
#include <app/ReadClient.h>
#include <app/ReadHandler.h>
#include <app/reporting/Engine.h>
#include <app/ClusterInfo.h>
#include <app/util/basic-types.h>

#define CHIP_MAX_NUM_COMMAND_HANDLER 1
#define CHIP_MAX_NUM_COMMAND_SENDER 1
#define CHIP_MAX_NUM_READ_CLIENT 1
#define CHIP_MAX_NUM_READ_HANDLER 1
#define CHIP_MAX_REPORTS_IN_FLIGHT 1
#define IM_SERVER_MAX_NUM_PATH_GROUPS 256

namespace chip {
namespace app {
Expand Down Expand Up @@ -127,6 +130,9 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate

reporting::Engine & GetReportingEngine() { return mReportingEngine; }

void ReleaseClusterInfoListToPool(ReadHandler * const apReadHandler);

CHIP_ERROR GetFirstAvailableClusterInfo(ClusterInfo *& apClusterInfo);
private:
friend class reporting::Engine;
void OnUnknownMsgType(Messaging::ExchangeContext * apExchangeContext, const PacketHeader & aPacketHeader,
Expand All @@ -151,10 +157,15 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate
ReadClient mReadClients[CHIP_MAX_NUM_READ_CLIENT];
ReadHandler mReadHandlers[CHIP_MAX_NUM_READ_HANDLER];
reporting::Engine mReportingEngine;
size_t mNumClusterInfos = 0;
ClusterInfo mClusterInfoPool[IM_SERVER_MAX_NUM_PATH_GROUPS];
};

void DispatchSingleClusterCommand(chip::ClusterId aClusterId, chip::CommandId aCommandId, chip::EndpointId aEndPointId,
chip::TLV::TLVReader & aReader, Command * apCommandObj);

CHIP_ERROR ReadSingleClusterData(NodeId aNodeId, ClusterId aClusterId, EndpointId aEndPointId, FieldId aFieldId,
TLV::TLVWriter & aWriter);
CHIP_ERROR WriteSingleClusterData(NodeId aNodeId, ClusterId aClusterId, EndpointId aEndPointId, FieldId aFieldId,
TLV::TLVReader & aReader);
} // namespace app
} // namespace chip
103 changes: 100 additions & 3 deletions src/app/ReadClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ void ReadClient::MoveToState(const ClientState aTargetState)
}

CHIP_ERROR ReadClient::SendReadRequest(NodeId aNodeId, Transport::AdminId aAdminId, EventPathParams * apEventPathParamsList,
size_t aEventPathParamsListSize)
size_t aEventPathParamsListSize, AttributePathParams * apAttributePathParamsList, size_t aAttributePathParamsListSize)
{
CHIP_ERROR err = CHIP_NO_ERROR;
System::PacketBufferHandle msgBuf;
Expand All @@ -104,6 +104,31 @@ CHIP_ERROR ReadClient::SendReadRequest(NodeId aNodeId, Transport::AdminId aAdmin
{
// TODO: fill to construct event paths
}

if (aAttributePathParamsListSize != 0 && apAttributePathParamsList != nullptr)
{
AttributePathList::Builder attributePathListBuilder = request.CreateAttributePathListBuilder();
SuccessOrExit(attributePathListBuilder.GetError());
for (size_t index = 0; index < aAttributePathParamsListSize; index++)
{
AttributePath::Builder attributePathBuilder = attributePathListBuilder.CreateAttributePathBuilder();
attributePathBuilder.NodeId(apAttributePathParamsList[index].mNodeId).EndpointId(apAttributePathParamsList[index].mEndpointId).ClusterId(apAttributePathParamsList[index].mClusterId);
if (apAttributePathParamsList[index].mFlags == AttributePathFlags::kFieldIdValid)
{
attributePathBuilder.FieldId(apAttributePathParamsList[index].mFieldId);
}
else if (apAttributePathParamsList[index].mFlags == AttributePathFlags::kListIndexValid)
{
attributePathBuilder.ListIndex(apAttributePathParamsList[index].mListIndex);
}
else
{
err = CHIP_ERROR_INVALID_ARGUMENT;
goto exit;
}
SuccessOrExit(attributePathBuilder.GetError());
}
}
request.EndOfReadRequest();
SuccessOrExit(request.GetError());

Expand Down Expand Up @@ -133,13 +158,13 @@ void ReadClient::OnMessageReceived(Messaging::ExchangeContext * apExchangeContex
err = CHIP_ERROR_INVALID_MESSAGE_TYPE);
VerifyOrExit(apExchangeContext == mpExchangeCtx, err = CHIP_ERROR_INCORRECT_STATE);
err = ProcessReportData(std::move(aPayload));

ChipLogProgress(DataManagement, "yunhan debug!!!!!!!!!!");
exit:
ChipLogFunctError(err);

ClearExistingExchangeContext();
MoveToState(ClientState::Initialized);

ChipLogProgress(DataManagement, "yunhan debug1!!!!!!!!!!");
if (mpDelegate != nullptr)
{
if (err != CHIP_NO_ERROR)
Expand Down Expand Up @@ -172,6 +197,7 @@ CHIP_ERROR ReadClient::ProcessReportData(System::PacketBufferHandle aPayload)
ReportData::Parser report;

bool isEventListPresent = false;
bool isAttributeDataListPresent = false;
bool suppressResponse = false;
bool moreChunkedMessages = false;

Expand Down Expand Up @@ -228,6 +254,30 @@ CHIP_ERROR ReadClient::ProcessReportData(System::PacketBufferHandle aPayload)
}
}

{
AttributeDataList::Parser attributeDataList;

err = report.GetAttributeDataList(&attributeDataList);
if (CHIP_NO_ERROR == err)
{
isAttributeDataListPresent = true;
}
else if (CHIP_END_OF_TLV == err)
{
isAttributeDataListPresent = false;
err = CHIP_NO_ERROR;
}
SuccessOrExit(err);

if (isAttributeDataListPresent && nullptr != mpDelegate && !moreChunkedMessages)
{
chip::TLV::TLVReader attributeDataListReader;
attributeDataList.GetReader(&attributeDataListReader);
err = ProcessAttributeDataList(attributeDataListReader);
SuccessOrExit(err);
}
}

if (!suppressResponse)
{
// TODO: Add status report support and correspond handler in ReadHandler, particular for situation when there
Expand All @@ -250,5 +300,52 @@ void ReadClient::OnResponseTimeout(Messaging::ExchangeContext * apExchangeContex
mpDelegate->ReportError(this, CHIP_ERROR_TIMEOUT);
}
}

CHIP_ERROR ReadClient::ProcessAttributeDataList(TLV::TLVReader & aAttributeDataListReader)
{
CHIP_ERROR err = CHIP_NO_ERROR;
while (CHIP_NO_ERROR == (err = aAttributeDataListReader.Next()))
{
NodeId nodeId = 0;
EndpointId endpointId = 0;
ClusterId clusterId = 0;
FieldId fieldId = 0;
chip::TLV::TLVReader dataReader;
AttributeDataElement::Parser element;
AttributePath::Parser attributePathParser;
TLV::TLVReader reader = aAttributeDataListReader;
err = element.Init(reader);
SuccessOrExit(err);

err = element.GetAttributePath(&attributePathParser);
SuccessOrExit(err);

err = attributePathParser.GetNodeId(&nodeId);
SuccessOrExit(err);

err = attributePathParser.GetEndpointId(&endpointId);
SuccessOrExit(err);

err = attributePathParser.GetClusterId(&clusterId);
SuccessOrExit(err);

err = attributePathParser.GetFieldId(&fieldId);
SuccessOrExit(err);

err = element.GetData(&dataReader);
SuccessOrExit(err);
err = WriteSingleClusterData(nodeId, clusterId, endpointId, fieldId, dataReader);
SuccessOrExit(err);
}

if (CHIP_END_OF_TLV == err)
{
err = CHIP_NO_ERROR;
}

exit:
ChipLogFunctError(err);
return err;
}
}; // namespace app
}; // namespace chip
7 changes: 6 additions & 1 deletion src/app/ReadClient.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,14 @@ class ReadClient : public Messaging::ExchangeDelegate
* @param[in] aAdminId Admin ID
* @param[in] apEventPathParamsList a list of event paths the read client is interested in
* @param[in] aEventPathParamsListSize Number of event paths in apEventPathParamsList
* @param[in] apAttributePathParamsList a list of attribute paths the read client is interested in
* @param[in] aAttributePathParamsListSize Number of attribute paths in apAttributePathParamsList
* @retval #others fail to send read request
* @retval #CHIP_NO_ERROR On success.
*/
CHIP_ERROR SendReadRequest(NodeId aNodeId, Transport::AdminId aAdminId, EventPathParams * apEventPathParamsList,
size_t aEventPathParamsListSize);
size_t aEventPathParamsListSize, AttributePathParams * apAttributePathParamsList,
size_t aAttributePathParamsListSize);

private:
friend class TestReadInteraction;
Expand Down Expand Up @@ -114,6 +117,8 @@ class ReadClient : public Messaging::ExchangeDelegate
*/
bool IsFree() const { return mState == ClientState::Uninitialized; };

CHIP_ERROR ProcessAttributeDataList(TLV::TLVReader & aAttributeDataListReader);

void MoveToState(const ClientState aTargetState);
CHIP_ERROR ProcessReportData(System::PacketBufferHandle aPayload);
CHIP_ERROR ClearExistingExchangeContext();
Expand Down
Loading

0 comments on commit 6fa241b

Please sign in to comment.