Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DataVersionFilter for read/subscribe #14711

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
yunhanw-google marked this conversation as resolved.
Show resolved Hide resolved
};

} // 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;
yunhanw-google marked this conversation as resolved.
Show resolved Hide resolved
Optional<DataVersion> mDataVersion;
yunhanw-google marked this conversation as resolved.
Show resolved Hide resolved
};
} // 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);
yunhanw-google marked this conversation as resolved.
Show resolved Hide resolved
} // 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