Skip to content

Commit

Permalink
Add IM/Ember Read/Writer Interface and attribute read for IM (#6214)
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 authored and pull[bot] committed Jul 5, 2021
1 parent 360c8c2 commit 2165682
Show file tree
Hide file tree
Showing 19 changed files with 582 additions and 61 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
4 changes: 3 additions & 1 deletion src/app/ClusterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,14 @@ 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; }
bool IsSamePath(const ClusterInfo & other) const { return other.mAttributePathParams.IsSamePath(mAttributePathParams); }
AttributePathParams mAttributePathParams;
bool mDirty = false;
bool mDirty = false;
ClusterInfo * mpNext = nullptr;
};
} // namespace app
} // namespace chip
12 changes: 8 additions & 4 deletions src/app/CommandHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,14 @@ CHIP_ERROR CommandHandler::ProcessCommandDataElement(CommandDataElement::Parser
chip::CommandId commandId;
chip::EndpointId endpointId;

SuccessOrExit(aCommandElement.GetCommandPath(&commandPath));
SuccessOrExit(commandPath.GetClusterId(&clusterId));
SuccessOrExit(commandPath.GetCommandId(&commandId));
SuccessOrExit(commandPath.GetEndpointId(&endpointId));
err = aCommandElement.GetCommandPath(&commandPath);
SuccessOrExit(err);
err = commandPath.GetClusterId(&clusterId);
SuccessOrExit(err);
err = commandPath.GetCommandId(&commandId);
SuccessOrExit(err);
err = commandPath.GetEndpointId(&endpointId);
SuccessOrExit(err);

err = aCommandElement.GetData(&commandDataReader);
if (CHIP_END_OF_TLV == err)
Expand Down
71 changes: 71 additions & 0 deletions src/app/InteractionModelEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ CHIP_ERROR InteractionModelEngine::Init(Messaging::ExchangeManager * apExchangeM
mReportingEngine.Init();
SuccessOrExit(err);

for (uint32_t index = 0; index < IM_SERVER_MAX_NUM_PATH_GROUPS - 1; index++)
{
mClusterInfoPool[index].mpNext = &mClusterInfoPool[index + 1];
}
mClusterInfoPool[IM_SERVER_MAX_NUM_PATH_GROUPS - 1].mpNext = nullptr;
mpNextAvailableClusterInfo = mClusterInfoPool;

exit:
return err;
}
Expand All @@ -78,6 +85,13 @@ void InteractionModelEngine::Shutdown()
{
readHandler.Shutdown();
}

for (uint32_t index = 0; index < IM_SERVER_MAX_NUM_PATH_GROUPS; index++)
{
mClusterInfoPool[index].mpNext = nullptr;
mClusterInfoPool[index].ClearDirty();
}
mpNextAvailableClusterInfo = nullptr;
}

CHIP_ERROR InteractionModelEngine::NewCommandSender(CommandSender ** const apCommandSender)
Expand Down Expand Up @@ -240,9 +254,66 @@ 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(AttributePathParams & aAttributePathParams, TLV::TLVWriter & aWriter)
{
ChipLogDetail(DataManagement,
"Received Cluster Command: Cluster=%" PRIx16 " NodeId=%" PRIx64 " Endpoint=%" PRIx8 " FieldId=%" PRIx8
" ListIndex=%" PRIx8,
aAttributePathParams.mClusterId, aAttributePathParams.mNodeId, aAttributePathParams.mEndpointId,
aAttributePathParams.mFieldId, aAttributePathParams.mListIndex);
ChipLogError(DataManagement,
"Default ReadSingleClusterData is called, this should be replaced by actual dispatched for cluster");
return CHIP_NO_ERROR;
}

CHIP_ERROR __attribute__((weak)) WriteSingleClusterData(AttributePathParams & aAttributePathParams, TLV::TLVReader & aReader)
{
ChipLogDetail(DataManagement,
"Received Cluster Attribute: Cluster=%" PRIx16 " NodeId=%" PRIx64 " Endpoint=%" PRIx8 " FieldId=%" PRIx8,
" ListIndex=%" PRIx8, aAttributePathParams.mClusterId, aAttributePathParams.mNodeId,
aAttributePathParams.mEndpointId, aAttributePathParams.mFieldId, aAttributePathParams.mListIndex);
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);
}

void InteractionModelEngine::ReleaseClusterInfoList(ClusterInfo *& aClusterInfo)
{
ClusterInfo * lastClusterInfo = aClusterInfo;
if (lastClusterInfo == nullptr)
{
return;
}

while (lastClusterInfo != nullptr && lastClusterInfo->mpNext != nullptr)
{
lastClusterInfo->ClearDirty();
lastClusterInfo = lastClusterInfo->mpNext;
}
lastClusterInfo->ClearDirty();
lastClusterInfo->mpNext = mpNextAvailableClusterInfo;
mpNextAvailableClusterInfo = aClusterInfo;
aClusterInfo = nullptr;
}

CHIP_ERROR InteractionModelEngine::PushFront(ClusterInfo *& aClusterInfo, AttributePathParams & aAttributePathParams)
{
ClusterInfo * last = aClusterInfo;
if (mpNextAvailableClusterInfo == nullptr)
{
return CHIP_ERROR_NO_MEMORY;
}
aClusterInfo = mpNextAvailableClusterInfo;
mpNextAvailableClusterInfo = mpNextAvailableClusterInfo->mpNext;
aClusterInfo->mpNext = last;
aClusterInfo->mAttributePathParams = aAttributePathParams;
return CHIP_NO_ERROR;
}

} // namespace app
} // namespace chip
13 changes: 11 additions & 2 deletions src/app/InteractionModelEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,26 +37,29 @@
#include <support/logging/CHIPLogging.h>
#include <system/SystemPacketBuffer.h>

#include <app/ClusterInfo.h>
#include <app/Command.h>
#include <app/CommandHandler.h>
#include <app/CommandSender.h>
#include <app/InteractionModelDelegate.h>
#include <app/ReadClient.h>
#include <app/ReadHandler.h>
#include <app/reporting/Engine.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 {

constexpr size_t kMaxSecureSduLengthBytes = 1024;
constexpr uint32_t kImMessageTimeoutMsec = 3000;

constexpr FieldId kRootFieldId = 0;
/**
* @class InteractionModelEngine
*
Expand Down Expand Up @@ -127,6 +130,9 @@ class InteractionModelEngine : public Messaging::ExchangeDelegate

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

void ReleaseClusterInfoList(ClusterInfo *& aClusterInfo);
CHIP_ERROR PushFront(ClusterInfo *& aClusterInfo, AttributePathParams & aAttributePathParams);

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

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

CHIP_ERROR ReadSingleClusterData(AttributePathParams & aAttributePathParams, TLV::TLVWriter & aWriter);
CHIP_ERROR WriteSingleClusterData(AttributePathParams & aAttributePathParams, TLV::TLVReader & aReader);
} // namespace app
} // namespace chip
140 changes: 114 additions & 26 deletions src/app/ReadClient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ 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 +105,33 @@ 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;
ExitNow();
}
SuccessOrExit(attributePathBuilder.GetError());
}
}
request.EndOfReadRequest();
SuccessOrExit(request.GetError());

Expand Down Expand Up @@ -139,7 +167,6 @@ void ReadClient::OnMessageReceived(Messaging::ExchangeContext * apExchangeContex

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

if (mpDelegate != nullptr)
{
if (err != CHIP_NO_ERROR)
Expand Down Expand Up @@ -171,10 +198,12 @@ CHIP_ERROR ReadClient::ProcessReportData(System::PacketBufferHandle aPayload)
CHIP_ERROR err = CHIP_NO_ERROR;
ReportData::Parser report;

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

bool isEventListPresent = false;
bool isAttributeDataListPresent = false;
bool suppressResponse = false;
bool moreChunkedMessages = false;
EventList::Parser eventList;
AttributeDataList::Parser attributeDataList;
System::PacketBufferTLVReader reader;

reader.Init(std::move(aPayload));
Expand Down Expand Up @@ -202,30 +231,35 @@ CHIP_ERROR ReadClient::ProcessReportData(System::PacketBufferHandle aPayload)
}
SuccessOrExit(err);

err = report.GetEventDataList(&eventList);
isEventListPresent = (err == CHIP_NO_ERROR);
if (err == CHIP_END_OF_TLV)
{
EventList::Parser eventList;
err = CHIP_NO_ERROR;
}
SuccessOrExit(err);

err = report.GetEventDataList(&eventList);
if (CHIP_NO_ERROR == err)
{
isEventListPresent = true;
}
else if (CHIP_END_OF_TLV == err)
{
isEventListPresent = false;
err = CHIP_NO_ERROR;
}
if (isEventListPresent && nullptr != mpDelegate)
{
chip::TLV::TLVReader eventListReader;
eventList.GetReader(&eventListReader);
err = mpDelegate->EventStreamReceived(mpExchangeCtx, &eventListReader);
SuccessOrExit(err);
}

VerifyOrExit(moreChunkedMessages == false, err = CHIP_ERROR_MESSAGE_INCOMPLETE);

if (isEventListPresent && nullptr != mpDelegate)
{
chip::TLV::TLVReader eventListReader;
eventList.GetReader(&eventListReader);
err = mpDelegate->EventStreamReceived(mpExchangeCtx, &eventListReader);
SuccessOrExit(err);
}
err = report.GetAttributeDataList(&attributeDataList);
isAttributeDataListPresent = (err == CHIP_NO_ERROR);
if (err == CHIP_END_OF_TLV)
{
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)
Expand All @@ -250,5 +284,59 @@ 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()))
{
chip::TLV::TLVReader dataReader;
AttributeDataElement::Parser element;
AttributePath::Parser attributePathParser;
AttributePathParams attributePathParams;
TLV::TLVReader reader = aAttributeDataListReader;
err = element.Init(reader);
SuccessOrExit(err);

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

err = attributePathParser.GetNodeId(&(attributePathParams.mNodeId));
SuccessOrExit(err);

err = attributePathParser.GetEndpointId(&(attributePathParams.mEndpointId));
SuccessOrExit(err);

err = attributePathParser.GetClusterId(&(attributePathParams.mClusterId));
SuccessOrExit(err);

err = attributePathParser.GetFieldId(&(attributePathParams.mFieldId));
if (CHIP_NO_ERROR == err)
{
attributePathParams.mFlags = AttributePathFlags::kFieldIdValid;
}
else if (CHIP_END_OF_TLV == err)
{
err = attributePathParser.GetListIndex(&(attributePathParams.mListIndex));
SuccessOrExit(err);
attributePathParams.mFlags = AttributePathFlags::kListIndexValid;
}
SuccessOrExit(err);

err = element.GetData(&dataReader);
SuccessOrExit(err);
err = WriteSingleClusterData(attributePathParams, dataReader);
SuccessOrExit(err);
}

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

exit:
ChipLogFunctError(err);
return err;
}
}; // namespace app
}; // namespace chip
Loading

0 comments on commit 2165682

Please sign in to comment.