Skip to content

Commit

Permalink
Add DataVersionFilter for read/subscribe (#14711)
Browse files Browse the repository at this point in the history
* Add DataVersionFilter support for read/subscribe
  • Loading branch information
yunhanw-google authored and pull[bot] committed Mar 3, 2022
1 parent 62e26db commit 3943297
Show file tree
Hide file tree
Showing 50 changed files with 1,041 additions and 311 deletions.
25 changes: 21 additions & 4 deletions examples/chip-tool/commands/clusters/ReportCommand.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class ReportCommand : public ModelCommand, public chip::app::ReadClient::Callbac
virtual void OnEventSubscription(){};

/////////// ReadClient Callback Interface /////////
void OnAttributeData(const chip::app::ConcreteDataAttributePath & path, chip::DataVersion aVersion, chip::TLV::TLVReader * data,
void OnAttributeData(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data,
const chip::app::StatusIB & status) override
{
CHIP_ERROR error = status.ToChipError();
Expand Down Expand Up @@ -108,7 +108,8 @@ class ReportCommand : public ModelCommand, public chip::app::ReadClient::Callbac
protected:
CHIP_ERROR ReportAttribute(ChipDevice * device, chip::EndpointId endpointId, chip::ClusterId clusterId,
chip::AttributeId attributeId, chip::app::ReadClient::InteractionType interactionType,
uint16_t minInterval = 0, uint16_t maxInterval = 0)
uint16_t minInterval = 0, uint16_t maxInterval = 0,
const chip::Optional<chip::DataVersion> & aDataVersion = chip::NullOptional)
{
chip::app::AttributePathParams attributePathParams[1];
attributePathParams[0].mEndpointId = endpointId;
Expand All @@ -121,6 +122,13 @@ class ReportCommand : public ModelCommand, public chip::app::ReadClient::Callbac
params.mpAttributePathParamsList = attributePathParams;
params.mAttributePathParamsListSize = 1;

chip::Optional<chip::app::DataVersionFilter> dataVersionFilter;
if (aDataVersion.HasValue())
{
params.mpDataVersionFilterList = &dataVersionFilter.Emplace(endpointId, clusterId, aDataVersion.Value());
params.mDataVersionFilterListSize = 1;
}

if (interactionType == chip::app::ReadClient::InteractionType::Subscribe)
{
params.mMinIntervalFloorSeconds = minInterval;
Expand Down Expand Up @@ -169,13 +177,15 @@ class ReadAttribute : public ReportCommand
{
AddArgument("cluster-id", 0, UINT32_MAX, &mClusterId);
AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
AddArgument("data-version", 0, UINT32_MAX, &mDataVersion);
ReportCommand::AddArguments();
}

ReadAttribute(chip::ClusterId clusterId, CredentialIssuerCommands * credsIssuerConfig) :
ReportCommand("read-by-id", credsIssuerConfig), mClusterId(clusterId)
{
AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
AddArgument("data-version", 0, UINT32_MAX, &mDataVersion);
ReportCommand::AddArguments();
}

Expand All @@ -185,6 +195,7 @@ class ReadAttribute : public ReportCommand
mClusterId(clusterId), mAttributeId(attributeId)
{
AddArgument("attr-name", attributeName);
AddArgument("data-version", 0, UINT32_MAX, &mDataVersion);
ReportCommand::AddArguments();
}

Expand All @@ -195,12 +206,13 @@ class ReadAttribute : public ReportCommand
ChipLogProgress(chipTool, "Sending ReadAttribute to cluster " ChipLogFormatMEI " on endpoint %" PRIu16,
ChipLogValueMEI(mClusterId), endpointId);
return ReportCommand::ReportAttribute(device, endpointId, mClusterId, mAttributeId,
chip::app::ReadClient::InteractionType::Read);
chip::app::ReadClient::InteractionType::Read, 0, 0, mDataVersion);
}

private:
chip::ClusterId mClusterId;
chip::AttributeId mAttributeId;
chip::Optional<chip::DataVersion> mDataVersion;
};

class SubscribeAttribute : public ReportCommand
Expand All @@ -212,6 +224,7 @@ class SubscribeAttribute : public ReportCommand
AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
AddArgument("min-interval", 0, UINT16_MAX, &mMinInterval);
AddArgument("max-interval", 0, UINT16_MAX, &mMaxInterval);
AddArgument("data-version", 0, UINT32_MAX, &mDataVersion);
AddArgument("wait", 0, 1, &mWait);
ReportCommand::AddArguments();
}
Expand All @@ -222,6 +235,7 @@ class SubscribeAttribute : public ReportCommand
AddArgument("attribute-id", 0, UINT32_MAX, &mAttributeId);
AddArgument("min-interval", 0, UINT16_MAX, &mMinInterval);
AddArgument("max-interval", 0, UINT16_MAX, &mMaxInterval);
AddArgument("data-version", 0, UINT32_MAX, &mDataVersion);
AddArgument("wait", 0, 1, &mWait);
ReportCommand::AddArguments();
}
Expand All @@ -234,6 +248,7 @@ class SubscribeAttribute : public ReportCommand
AddArgument("attr-name", attributeName);
AddArgument("min-interval", 0, UINT16_MAX, &mMinInterval);
AddArgument("max-interval", 0, UINT16_MAX, &mMaxInterval);
AddArgument("data-version", 0, UINT32_MAX, &mDataVersion);
AddArgument("wait", 0, 1, &mWait);
ReportCommand::AddArguments();
}
Expand All @@ -245,7 +260,8 @@ class SubscribeAttribute : public ReportCommand
ChipLogProgress(chipTool, "Sending SubscribeAttribute to cluster " ChipLogFormatMEI " on endpoint %" PRIu16,
ChipLogValueMEI(mClusterId), endpointId);
return ReportCommand::ReportAttribute(device, endpointId, mClusterId, mAttributeId,
chip::app::ReadClient::InteractionType::Subscribe, mMinInterval, mMaxInterval);
chip::app::ReadClient::InteractionType::Subscribe, mMinInterval, mMaxInterval,
mDataVersion);
}

chip::System::Clock::Timeout GetWaitDuration() const override
Expand All @@ -267,6 +283,7 @@ class SubscribeAttribute : public ReportCommand

uint16_t mMinInterval;
uint16_t mMaxInterval;
chip::Optional<chip::DataVersion> mDataVersion;
bool mWait;
};

Expand Down
4 changes: 2 additions & 2 deletions examples/chip-tool/templates/logging/DataModelLogger-src.zapt
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, const {{

CHIP_ERROR DataModelLogger::LogAttribute(const chip::app::ConcreteDataAttributePath & path, chip::TLV::TLVReader * data)
{
ChipLogProgress(chipTool, "Endpoint: %" PRIu16 " Cluster: " ChipLogFormatMEI " Attribute " ChipLogFormatMEI, path.mEndpointId,
ChipLogValueMEI(path.mClusterId), ChipLogValueMEI(path.mAttributeId));
ChipLogProgress(chipTool, "Endpoint: %" PRIu16 " Cluster: " ChipLogFormatMEI " Attribute " ChipLogFormatMEI "DataVersion: %" PRIu32, path.mEndpointId,
ChipLogValueMEI(path.mClusterId), ChipLogValueMEI(path.mAttributeId), path.mDataVersion);

switch (path.mClusterId)
{
Expand Down
5 changes: 2 additions & 3 deletions src/app/AttributeCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,7 @@ void AttributeCache::OnReportEnd()
mCallback.OnReportEnd();
}

void AttributeCache::OnAttributeData(const ConcreteDataAttributePath & aPath, DataVersion aVersion, TLV::TLVReader * apData,
const StatusIB & aStatus)
void AttributeCache::OnAttributeData(const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData, const StatusIB & aStatus)
{
//
// Since the cache itself is a ReadClient::Callback, it may be incorrectly passed in directly when registering with the
Expand All @@ -121,7 +120,7 @@ void AttributeCache::OnAttributeData(const ConcreteDataAttributePath & aPath, Da
//
// Forward the call through.
//
mCallback.OnAttributeData(aPath, aVersion, apData, aStatus);
mCallback.OnAttributeData(aPath, apData, aStatus);
}

CHIP_ERROR AttributeCache::Get(const ConcreteAttributePath & path, TLV::TLVReader & reader)
Expand Down
3 changes: 1 addition & 2 deletions src/app/AttributeCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,7 @@ class AttributeCache : protected ReadClient::Callback
//
void OnReportBegin() override;
void OnReportEnd() override;
void OnAttributeData(const ConcreteDataAttributePath & aPath, DataVersion aVersion, TLV::TLVReader * apData,
const StatusIB & aStatus) override;
void OnAttributeData(const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData, const StatusIB & aStatus) override;
void OnError(CHIP_ERROR aError) override { return mCallback.OnError(aError); }

void OnEventData(const EventHeader & aEventHeader, TLV::TLVReader * apData, const StatusIB * apStatus) override
Expand Down
7 changes: 3 additions & 4 deletions src/app/BufferedReadCallback.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ CHIP_ERROR BufferedReadCallback::DispatchBufferedData(const ConcreteAttributePat
//
ReturnErrorOnFailure(reader.Next());

mCallback.OnAttributeData(mBufferedPath, mDataVersion, &reader, statusIB);
mCallback.OnAttributeData(mBufferedPath, &reader, statusIB);

//
// Clear out our buffered contents to free up allocated buffers, and reset the buffered path.
Expand All @@ -225,7 +225,7 @@ CHIP_ERROR BufferedReadCallback::DispatchBufferedData(const ConcreteAttributePat
return CHIP_NO_ERROR;
}

void BufferedReadCallback::OnAttributeData(const ConcreteDataAttributePath & aPath, DataVersion aVersion, TLV::TLVReader * apData,
void BufferedReadCallback::OnAttributeData(const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData,
const StatusIB & aStatus)
{
CHIP_ERROR err;
Expand All @@ -246,14 +246,13 @@ void BufferedReadCallback::OnAttributeData(const ConcreteDataAttributePath & aPa
}
else
{
mCallback.OnAttributeData(aPath, aVersion, apData, aStatus);
mCallback.OnAttributeData(aPath, apData, aStatus);
}

//
// Update our latched buffered path.
//
mBufferedPath = aPath;
mDataVersion = aVersion;

exit:
if (err != CHIP_NO_ERROR)
Expand Down
4 changes: 1 addition & 3 deletions src/app/BufferedReadCallback.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@ class BufferedReadCallback : public ReadClient::Callback
//
void OnReportBegin() override;
void OnReportEnd() override;
void OnAttributeData(const ConcreteDataAttributePath & aPath, DataVersion aVersion, TLV::TLVReader * apData,
const StatusIB & aStatus) override;
void OnAttributeData(const ConcreteDataAttributePath & aPath, TLV::TLVReader * apData, const StatusIB & aStatus) override;
void OnError(CHIP_ERROR aError) override { return mCallback.OnError(aError); }
void OnEventData(const EventHeader & aEventHeader, TLV::TLVReader * apData, const StatusIB * apStatus) override
{
Expand All @@ -94,7 +93,6 @@ class BufferedReadCallback : public ReadClient::Callback
*
*/
CHIP_ERROR BufferListItem(TLV::TLVReader & reader);
DataVersion mDataVersion;
ConcreteDataAttributePath mBufferedPath;
std::vector<System::PacketBufferHandle> mBufferedList;
Callback & mCallback;
Expand Down
3 changes: 3 additions & 0 deletions src/app/ClusterInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ struct ClusterInfo
// For event, an event id can only be interpreted if the cluster id is known.
bool IsValidEventPath() const { return !(HasWildcardClusterId() && !HasWildcardEventId()); }

bool IsValidDataVersionFilter() const { return !HasWildcardEndpointId() && !HasWildcardClusterId() && mDataVersion.HasValue(); }

inline bool HasWildcardNodeId() const { return mNodeId == kUndefinedNodeId; }
inline bool HasWildcardEndpointId() const { return mEndpointId == kInvalidEndpointId; }
inline bool HasWildcardClusterId() const { return mClusterId == kInvalidClusterId; }
Expand All @@ -100,6 +102,7 @@ struct ClusterInfo
EventId mEventId = kInvalidEventId; // uint32
ListIndex mListIndex = kInvalidListIndex; // uint16
EndpointId mEndpointId = kInvalidEndpointId; // uint16
Optional<DataVersion> mDataVersion; // uint32
};
} // namespace app
} // namespace chip
9 changes: 7 additions & 2 deletions src/app/ConcreteAttributePath.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ struct ConcreteDataAttributePath : public ConcreteAttributePath
ConcreteAttributePath(aEndpointId, aClusterId, aAttributeId)
{}

ConcreteDataAttributePath(EndpointId aEndpointId, ClusterId aClusterId, AttributeId aAttributeId, DataVersion aDataVersion) :
ConcreteAttributePath(aEndpointId, aClusterId, aAttributeId), mDataVersion(aDataVersion)
{}

ConcreteDataAttributePath(EndpointId aEndpointId, ClusterId aClusterId, AttributeId aAttributeId, ListOperation aListOp,
uint16_t aListIndex) :
ConcreteAttributePath(aEndpointId, aClusterId, aAttributeId)
Expand All @@ -126,8 +130,9 @@ struct ConcreteDataAttributePath : public ConcreteAttributePath
// This index is only valid if `mListOp` is set to a list item operation, i.e
// ReplaceItem, DeleteItem or AppendItem. Otherwise, it is to be ignored.
//
uint16_t mListIndex = 0;
ListOperation mListOp = ListOperation::NotList;
uint16_t mListIndex = 0;
ListOperation mListOp = ListOperation::NotList;
DataVersion mDataVersion = 0;
};

} // namespace app
Expand Down
45 changes: 45 additions & 0 deletions src/app/DataVersionFilter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
*
* Copyright (c) 2022 Project CHIP Authors
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#pragma once

#include <app/util/basic-types.h>

#include <app/ClusterInfo.h>

namespace chip {
namespace app {
struct DataVersionFilter
{
DataVersionFilter(EndpointId aEndpointId, ClusterId aClusterId, DataVersion aDataVersion) :
mEndpointId(aEndpointId), mClusterId(aClusterId), mDataVersion(aDataVersion)
{}

DataVersionFilter() {}

bool IsValidDataVersionFilter()
{
return (mEndpointId != kInvalidEndpointId) && (mClusterId != kInvalidClusterId) && (mDataVersion.HasValue());
}

EndpointId mEndpointId = kInvalidEndpointId;
ClusterId mClusterId = kInvalidClusterId;
Optional<DataVersion> mDataVersion;
};
} // namespace app
} // namespace chip
5 changes: 5 additions & 0 deletions src/app/InteractionModelEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,5 +340,10 @@ CHIP_ERROR ReadSingleClusterData(const Access::SubjectDescriptor & aSubjectDescr
CHIP_ERROR WriteSingleClusterData(const Access::SubjectDescriptor & aSubjectDescriptor,
const ConcreteDataAttributePath & aAttributePath, TLV::TLVReader & aReader,
WriteHandler * apWriteHandler);

/**
* Check if the given cluster has the given DataVersion.
*/
bool IsClusterDataVersionEqual(EndpointId aEndpointId, ClusterId aClusterId, DataVersion aRequiredVersion);
} // namespace app
} // namespace chip
2 changes: 1 addition & 1 deletion src/app/MessageDef/ReadRequestMessage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ CHIP_ERROR ReadRequestMessage::Parser::CheckSchemaValidity() const
break;
case to_underlying(Tag::kDataVersionFilters):
// check if this tag has appeared before
VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kEventFilters))), CHIP_ERROR_INVALID_TLV_TAG);
VerifyOrReturnError(!(tagPresenceMask & (1 << to_underlying(Tag::kDataVersionFilters))), CHIP_ERROR_INVALID_TLV_TAG);
tagPresenceMask |= (1 << to_underlying(Tag::kDataVersionFilters));
{
DataVersionFilterIBs::Parser dataVersionFilters;
Expand Down
Loading

0 comments on commit 3943297

Please sign in to comment.