Skip to content

Commit

Permalink
Decouple ember-specific functions from descriptor cluster (#36493)
Browse files Browse the repository at this point in the history
* descriptor: decouple from ember

* Restyled by clang-format

* fix shadow error

* fix test build

* fix test build

* use Client cluster iteration

* Restyled by clang-format

* fix CI building error

* fix android build

* review changes

* Restyled by clang-format

* review changes

* some doc changes

* Fix the semantic tags iterator and add unit tests for the new functions

* Restyled by clang-format

* fix clang tidy check

* add composition test

* Restyled by clang-format

* Update src/app/data-model-provider/MetadataTypes.h

Co-authored-by: Boris Zbarsky <[email protected]>

* Update src/app/codegen-data-model-provider/CodegenDataModelProvider.cpp

Co-authored-by: Boris Zbarsky <[email protected]>

---------

Co-authored-by: Restyled.io <[email protected]>
Co-authored-by: Andrei Litvin <[email protected]>
Co-authored-by: Boris Zbarsky <[email protected]>
  • Loading branch information
4 people authored Nov 29, 2024
1 parent 19cbdf4 commit fb24b90
Show file tree
Hide file tree
Showing 22 changed files with 802 additions and 219 deletions.
2 changes: 1 addition & 1 deletion examples/common/pigweed/rpc_services/Attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ class Attributes : public pw_rpc::nanopb::Attributes::Service<Attributes>
request.operationFlags.Set(app::DataModel::OperationFlags::kInternal);
request.subjectDescriptor = &subjectDescriptor;

std::optional<app::DataModel::ClusterInfo> info = provider->GetClusterInfo(path);
std::optional<app::DataModel::ClusterInfo> info = provider->GetServerClusterInfo(path);
if (!info.has_value())
{
return ::pw::Status::NotFound();
Expand Down
14 changes: 7 additions & 7 deletions src/app/AttributePathExpandIterator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,13 +115,13 @@ std::optional<ClusterId> AttributePathExpandIterator::NextClusterId()
{
if (mpAttributePath->mValue.HasWildcardClusterId())
{
ClusterEntry entry = mDataModelProvider->FirstCluster(mOutputPath.mEndpointId);
ClusterEntry entry = mDataModelProvider->FirstServerCluster(mOutputPath.mEndpointId);
return entry.IsValid() ? std::make_optional(entry.path.mClusterId) : std::nullopt;
}

// only return a cluster if it is valid
const ConcreteClusterPath clusterPath(mOutputPath.mEndpointId, mpAttributePath->mValue.mClusterId);
if (!mDataModelProvider->GetClusterInfo(clusterPath).has_value())
if (!mDataModelProvider->GetServerClusterInfo(clusterPath).has_value())
{
return std::nullopt;
}
Expand All @@ -131,7 +131,7 @@ std::optional<ClusterId> AttributePathExpandIterator::NextClusterId()

VerifyOrReturnValue(mpAttributePath->mValue.HasWildcardClusterId(), std::nullopt);

ClusterEntry entry = mDataModelProvider->NextCluster(mOutputPath);
ClusterEntry entry = mDataModelProvider->NextServerCluster(mOutputPath);
return entry.IsValid() ? std::make_optional(entry.path.mClusterId) : std::nullopt;
}

Expand All @@ -141,17 +141,17 @@ std::optional<ClusterId> AttributePathExpandIterator::NextEndpointId()
{
if (mpAttributePath->mValue.HasWildcardEndpointId())
{
EndpointId id = mDataModelProvider->FirstEndpoint();
return (id != kInvalidEndpointId) ? std::make_optional(id) : std::nullopt;
EndpointEntry ep = mDataModelProvider->FirstEndpoint();
return (ep.id != kInvalidEndpointId) ? std::make_optional(ep.id) : std::nullopt;
}

return mpAttributePath->mValue.mEndpointId;
}

VerifyOrReturnValue(mpAttributePath->mValue.HasWildcardEndpointId(), std::nullopt);

EndpointId id = mDataModelProvider->NextEndpoint(mOutputPath.mEndpointId);
return (id != kInvalidEndpointId) ? std::make_optional(id) : std::nullopt;
EndpointEntry ep = mDataModelProvider->NextEndpoint(mOutputPath.mEndpointId);
return (ep.id != kInvalidEndpointId) ? std::make_optional(ep.id) : std::nullopt;
}

void AttributePathExpandIterator::ResetCurrentCluster()
Expand Down
16 changes: 7 additions & 9 deletions src/app/InteractionModelEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,14 @@ bool MayHaveAccessibleEventPathForEndpoint(DataModel::Provider * aProvider, Endp
aSubjectDescriptor);
}

DataModel::ClusterEntry clusterEntry = aProvider->FirstCluster(aEventPath.mEndpointId);
DataModel::ClusterEntry clusterEntry = aProvider->FirstServerCluster(aEventPath.mEndpointId);
while (clusterEntry.IsValid())
{
if (MayHaveAccessibleEventPathForEndpointAndCluster(clusterEntry.path, aEventPath, aSubjectDescriptor))
{
return true;
}
clusterEntry = aProvider->NextCluster(clusterEntry.path);
clusterEntry = aProvider->NextServerCluster(clusterEntry.path);
}

return false;
Expand All @@ -112,10 +112,9 @@ bool MayHaveAccessibleEventPath(DataModel::Provider * aProvider, const EventPath
return MayHaveAccessibleEventPathForEndpoint(aProvider, aEventPath.mEndpointId, aEventPath, subjectDescriptor);
}

for (EndpointId endpointId = aProvider->FirstEndpoint(); endpointId != kInvalidEndpointId;
endpointId = aProvider->NextEndpoint(endpointId))
for (DataModel::EndpointEntry ep = aProvider->FirstEndpoint(); ep.IsValid(); ep = aProvider->NextEndpoint(ep.id))
{
if (MayHaveAccessibleEventPathForEndpoint(aProvider, endpointId, aEventPath, subjectDescriptor))
if (MayHaveAccessibleEventPathForEndpoint(aProvider, ep.id, aEventPath, subjectDescriptor))
{
return true;
}
Expand Down Expand Up @@ -1793,17 +1792,16 @@ Protocols::InteractionModel::Status InteractionModelEngine::CheckCommandExistenc

// We failed, figure out why ...
//
if (provider->GetClusterInfo(aCommandPath).has_value())
if (provider->GetServerClusterInfo(aCommandPath).has_value())
{
return Protocols::InteractionModel::Status::UnsupportedCommand; // cluster exists, so command is invalid
}

// At this point either cluster or endpoint does not exist. If we find the endpoint, then the cluster
// is invalid
for (EndpointId endpoint = provider->FirstEndpoint(); endpoint != kInvalidEndpointId;
endpoint = provider->NextEndpoint(endpoint))
for (DataModel::EndpointEntry ep = provider->FirstEndpoint(); ep.IsValid(); ep = provider->NextEndpoint(ep.id))
{
if (endpoint == aCommandPath.mEndpointId)
if (ep.id == aCommandPath.mEndpointId)
{
// endpoint exists, so cluster is invalid
return Protocols::InteractionModel::Status::UnsupportedCluster;
Expand Down
109 changes: 56 additions & 53 deletions src/app/clusters/descriptor/descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <app-common/zap-generated/ids/Clusters.h>
#include <app/AttributeAccessInterface.h>
#include <app/AttributeAccessInterfaceRegistry.h>
#include <app/InteractionModelEngine.h>
#include <app/data-model-provider/MetadataTypes.h>
#include <app/util/attribute-storage.h>
#include <app/util/endpoint-config-api.h>
#include <lib/support/CodeUtils.h>
Expand Down Expand Up @@ -73,87 +75,77 @@ CHIP_ERROR DescriptorAttrAccess::ReadFeatureMap(EndpointId endpoint, AttributeVa
CHIP_ERROR DescriptorAttrAccess::ReadTagListAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder)
{
return aEncoder.EncodeList([&endpoint](const auto & encoder) -> CHIP_ERROR {
Clusters::Descriptor::Structs::SemanticTagStruct::Type tag;
size_t index = 0;
CHIP_ERROR err = CHIP_NO_ERROR;
while ((err = GetSemanticTagForEndpointAtIndex(endpoint, index, tag)) == CHIP_NO_ERROR)
auto tag = InteractionModelEngine::GetInstance()->GetDataModelProvider()->GetFirstSemanticTag(endpoint);
while (tag.has_value())
{
ReturnErrorOnFailure(encoder.Encode(tag));
index++;
ReturnErrorOnFailure(encoder.Encode(tag.value()));
tag = InteractionModelEngine::GetInstance()->GetDataModelProvider()->GetNextSemanticTag(endpoint, tag.value());
}
if (err == CHIP_ERROR_NOT_FOUND)
{
return CHIP_NO_ERROR;
}
return err;
return CHIP_NO_ERROR;
});
}

CHIP_ERROR DescriptorAttrAccess::ReadPartsAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder)
{
CHIP_ERROR err = CHIP_NO_ERROR;

auto endpointInfo = InteractionModelEngine::GetInstance()->GetDataModelProvider()->GetEndpointInfo(endpoint);
if (endpoint == 0x00)
{
err = aEncoder.EncodeList([](const auto & encoder) -> CHIP_ERROR {
for (uint16_t index = 0; index < emberAfEndpointCount(); index++)
auto endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstEndpoint();
while (endpointEntry.IsValid())
{
if (emberAfEndpointIndexIsEnabled(index))
if (endpointEntry.id != 0)
{
EndpointId endpointId = emberAfEndpointFromIndex(index);
if (endpointId == 0)
continue;

ReturnErrorOnFailure(encoder.Encode(endpointId));
ReturnErrorOnFailure(encoder.Encode(endpointEntry.id));
}
endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextEndpoint(endpointEntry.id);
}

return CHIP_NO_ERROR;
});
}
else if (IsFlatCompositionForEndpoint(endpoint))
else if (endpointInfo.has_value() &&
endpointInfo->compositionPattern == DataModel::EndpointCompositionPattern::kFullFamilyPattern)
{
err = aEncoder.EncodeList([endpoint](const auto & encoder) -> CHIP_ERROR {
for (uint16_t index = 0; index < emberAfEndpointCount(); index++)
auto endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstEndpoint();
while (endpointEntry.IsValid())
{
if (!emberAfEndpointIndexIsEnabled(index))
continue;

uint16_t childIndex = index;
while (childIndex != chip::kInvalidListIndex)
EndpointId parentEndpointId = endpointEntry.info.parentId;
while (parentEndpointId != chip::kInvalidEndpointId)
{
EndpointId parentEndpointId = emberAfParentEndpointFromIndex(childIndex);
if (parentEndpointId == chip::kInvalidEndpointId)
break;

if (parentEndpointId == endpoint)
{
ReturnErrorOnFailure(encoder.Encode(emberAfEndpointFromIndex(index)));
ReturnErrorOnFailure(encoder.Encode(endpointEntry.id));
break;
}

childIndex = emberAfIndexFromEndpoint(parentEndpointId);
auto parentEndpointInfo =
InteractionModelEngine::GetInstance()->GetDataModelProvider()->GetEndpointInfo(parentEndpointId);
if (!parentEndpointInfo.has_value())
{
break;
}
parentEndpointId = parentEndpointInfo->parentId;
}
endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextEndpoint(endpointEntry.id);
}

return CHIP_NO_ERROR;
});
}
else if (IsTreeCompositionForEndpoint(endpoint))
else if (endpointInfo.has_value() && endpointInfo->compositionPattern == DataModel::EndpointCompositionPattern::kTreePattern)
{
err = aEncoder.EncodeList([endpoint](const auto & encoder) -> CHIP_ERROR {
for (uint16_t index = 0; index < emberAfEndpointCount(); index++)
auto endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstEndpoint();
while (endpointEntry.IsValid())
{
if (!emberAfEndpointIndexIsEnabled(index))
continue;

EndpointId parentEndpointId = emberAfParentEndpointFromIndex(index);
if (parentEndpointId == endpoint)
if (endpointEntry.info.parentId == endpoint)
{
ReturnErrorOnFailure(encoder.Encode(emberAfEndpointFromIndex(index)));
ReturnErrorOnFailure(encoder.Encode(endpointEntry.id));
}
endpointEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextEndpoint(endpointEntry.id);
}

return CHIP_NO_ERROR;
});
}
Expand All @@ -165,16 +157,15 @@ CHIP_ERROR DescriptorAttrAccess::ReadDeviceAttribute(EndpointId endpoint, Attrib
{
CHIP_ERROR err = aEncoder.EncodeList([&endpoint](const auto & encoder) -> CHIP_ERROR {
Descriptor::Structs::DeviceTypeStruct::Type deviceStruct;
CHIP_ERROR err2;

auto deviceTypeList = emberAfDeviceTypeListFromEndpoint(endpoint, err2);
ReturnErrorOnFailure(err2);
auto deviceType = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstDeviceType(endpoint);

for (auto & deviceType : deviceTypeList)
while (deviceType.has_value())
{
deviceStruct.deviceType = deviceType.deviceId;
deviceStruct.revision = deviceType.deviceVersion;
deviceStruct.deviceType = deviceType->deviceTypeId;
deviceStruct.revision = deviceType->deviceTypeRevision;
ReturnErrorOnFailure(encoder.Encode(deviceStruct));
deviceType = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextDeviceType(endpoint, *deviceType);
}

return CHIP_NO_ERROR;
Expand All @@ -186,12 +177,24 @@ CHIP_ERROR DescriptorAttrAccess::ReadDeviceAttribute(EndpointId endpoint, Attrib
CHIP_ERROR DescriptorAttrAccess::ReadClientServerAttribute(EndpointId endpoint, AttributeValueEncoder & aEncoder, bool server)
{
CHIP_ERROR err = aEncoder.EncodeList([&endpoint, server](const auto & encoder) -> CHIP_ERROR {
uint8_t clusterCount = emberAfClusterCount(endpoint, server);

for (uint8_t clusterIndex = 0; clusterIndex < clusterCount; clusterIndex++)
if (server)
{
const EmberAfCluster * cluster = emberAfGetNthCluster(endpoint, clusterIndex, server);
ReturnErrorOnFailure(encoder.Encode(cluster->clusterId));
auto clusterEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstServerCluster(endpoint);
while (clusterEntry.IsValid())
{
ReturnErrorOnFailure(encoder.Encode(clusterEntry.path.mClusterId));
clusterEntry = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextServerCluster(clusterEntry.path);
}
}
else
{
ConcreteClusterPath clusterPath =
InteractionModelEngine::GetInstance()->GetDataModelProvider()->FirstClientCluster(endpoint);
while (clusterPath.HasValidIds())
{
ReturnErrorOnFailure(encoder.Encode(clusterPath.mClusterId));
clusterPath = InteractionModelEngine::GetInstance()->GetDataModelProvider()->NextClientCluster(clusterPath);
}
}

return CHIP_NO_ERROR;
Expand Down
Loading

0 comments on commit fb24b90

Please sign in to comment.