Skip to content

Commit

Permalink
[attribute storage] allow setting up dynamic endpoints from templates
Browse files Browse the repository at this point in the history
Instead of re-creating dynamic endpoint's cluster declarations
using the DECLARE_DYNAMIC_xxx macros, the new
`setupDynamicEndpointDeclaration()` function allows setting
up a dynamic endpoint by using clusters defined in another
endpoint as templates. Usually that is a disabled endpoint created
in ZAP with all possibly dynamically used clusters assigned.

In combination with dynamic endpoint attribute storage, this
greatly simplifies implementing dynamic endpoints and allows
configuring them using the ZAP tool to ensure specs conformance,
much the same way as with statically defined endpoints.
  • Loading branch information
plan44 committed Oct 11, 2024
1 parent efd6a81 commit 423b4fd
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 0 deletions.
34 changes: 34 additions & 0 deletions src/app/util/attribute-storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,40 @@ uint16_t emberAfGetDynamicIndexFromEndpoint(EndpointId id)
return kEmberInvalidEndpointIndex;
}

const EmberAfCluster * getClusterTypeDefinition(EndpointId endpointId, ClusterId clusterId, EmberAfClusterMask mask)
{
uint16_t index = emberAfIndexFromEndpointIncludingDisabledEndpoints(endpointId);
if (index != kEmberInvalidEndpointIndex)
{
return emberAfFindClusterInType(emAfEndpoints[index].endpointType, clusterId, mask, nullptr);
}
// not found
return nullptr;
}

CHIP_ERROR setupDynamicEndpointDeclaration(EmberAfEndpointType & endpointType, EndpointId templateEndpointId,
const Span<const ClusterId> & templateClusterIds)
{
// allocate cluster list
endpointType.clusterCount = static_cast<uint8_t>(templateClusterIds.size());
endpointType.cluster = new EmberAfCluster[endpointType.clusterCount];
endpointType.endpointSize = 0;
// get the actual cluster pointers and sum up memory size
for (size_t i = 0; i < templateClusterIds.size(); i++)
{
auto cluster = getClusterTypeDefinition(templateEndpointId, templateClusterIds.data()[i], 0);
VerifyOrDieWithMsg(cluster, Support, "cluster 0x%04x template in endpoint %u does not exist",
(unsigned int) templateClusterIds.data()[i], (unsigned int) templateEndpointId);
// for now, we need to copy the cluster definition, unfortunately.
// TODO: make endpointType use a pointer to a list of EmberAfCluster* instead, so we can re-use cluster definitions
// instead of duplicating them here once for every instance.
memcpy((void *) &endpointType.cluster[i], cluster, sizeof(EmberAfCluster));
// sum up the needed storage
endpointType.endpointSize = (uint16_t) (endpointType.endpointSize + cluster->clusterSize);
}
return CHIP_NO_ERROR;
}

CHIP_ERROR emberAfSetDynamicEndpoint(uint16_t index, EndpointId id, const EmberAfEndpointType * ep,
const chip::Span<DataVersion> & dataVersionStorage, Span<const EmberAfDeviceType> deviceTypeList,
EndpointId parentEndpointId, uint8_t * dynamicAttributeStorage)
Expand Down
12 changes: 12 additions & 0 deletions src/app/util/attribute-storage.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,18 @@ const EmberAfCluster * emberAfFindClusterInType(const EmberAfEndpointType * endp
// Initial configuration
void emberAfEndpointConfigure();

// setup a dynamic endpoint's EmberAfEndpointType from a list of template clusters.
//
// This is a alternative to declaring dynamic endpoint metadata using DECLARE_DYNAMIC_* macros.
//
// As clusters to be used in dynamic endpoint setup need to be defined in ZAP anyway
// (usually on a special endpoint which remains always disabled), the cluster's
// metadata including all attributes already exists and can be re-used this way,
// without error prone manual duplicating with DECLARE_DYNAMIC_*
//
CHIP_ERROR setupDynamicEndpointDeclaration(EmberAfEndpointType & endpointType, chip::EndpointId templateEndpointId,
const chip::Span<const chip::ClusterId> & templateClusterIds);

// Register a dynamic endpoint. This involves registering descriptors that describe
// the composition of the endpoint (encapsulated in the 'ep' argument) as well as providing
// storage for data versions.
Expand Down

0 comments on commit 423b4fd

Please sign in to comment.