src/app/clusters/identify-server/README.md
The Identify cluster is used to help an administrator identify a particular Node. For example, it can be used to cause an LED on a device to blink, a speaker to beep, or a display to show a QR code.
This directory contains a code-driven C++ implementation of the Matter Identify
cluster server. This implementation (IdentifyCluster.h) is designed for
flexibility avoiding the the tight coupling present in older ZAP/Ember based
implementations.
It uses a delegate pattern (chip::app::Clusters::IdentifyDelegate) to notify
the application about cluster-related events, such as when identification
starts, stops, or an effect is triggered.
To integrate the IdentifyCluster into your application, follow these steps:
Create a class that inherits from chip::app::Clusters::IdentifyDelegate and
implement its virtual methods to handle identification events.
#include "app/clusters/identify-server/IdentifyCluster.h"
class MyIdentifyDelegate : public chip::app::Clusters::IdentifyDelegate
{
public:
void OnIdentifyStart(chip::app::Clusters::IdentifyCluster & cluster) override
{
// Your logic to start identification (e.g., start blinking an LED)
}
void OnIdentifyStop(chip::app::Clusters::IdentifyCluster & cluster) override
{
// Your logic to stop identification (e.g., stop blinking an LED)
}
void OnTriggerEffect(chip::app::Clusters::IdentifyCluster & cluster) override
{
// Your logic to trigger a specific effect
}
bool IsTriggerEffectEnabled() const override { return true; }
};
Instantiate your delegate, a timer delegate, and the IdentifyCluster itself
for each endpoint that requires it. Using RegisteredServerCluster simplifies
registration.
#include "app/DefaultTimerDelegate.h"
#include "app/server-cluster/ServerClusterInterfaceRegistry.h"
// In a .cpp file
MyIdentifyDelegate gMyIdentifyDelegate;
DefaultTimerDelegate gTimerDelegate;
chip::app::RegisteredServerCluster<chip::app::Clusters::IdentifyCluster> gIdentifyCluster(
chip::app::Clusters::IdentifyCluster::Config(kYourEndpointId, gTimerDelegate)
.WithIdentifyType(chip::app::Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator)
.WithDelegate(&gMyIdentifyDelegate));
In your application's initialization sequence, register the cluster instance
with the CodegenDataModelProvider. This hooks the cluster into the Matter data
model and message processing framework.
#include "data-model-providers/codegen/CodegenDataModelProvider.h"
void ApplicationInit()
{
// ... other initializations
CHIP_ERROR err = chip::app::CodegenDataModelProvider::Instance().Registry().Register(gIdentifyCluster.Registration());
VerifyOrDie(err == CHIP_NO_ERROR);
// ...
}
For backwards compatibility with applications that rely on older ZAP-generated
patterns, a legacy API is provided in CodegenIntegration.h and
CodegenIntegration.cpp. This compatibility layer allows the application to
function without being immediately updated to the new code-driven approach.
However, this legacy approach is discouraged. It introduces significant code size overhead (~400 bytes) because it needs to add extra code to convert the new API to the old API.
We strongly recommend migrating to the new, direct instantiation method to improve performance and reduce your application's footprint.
The new approach is to instantiate the cluster directly and register it with the
CodegenDataModelProvider, as detailed in the "Usage" section above. This gives
you more control and results in a smaller, more efficient binary.
// In a header or source file:
#include "app/clusters/identify-server/IdentifyCluster.h"
#include "app/server-cluster/ServerClusterInterfaceRegistry.h"
#include "app/DefaultTimerDelegate.h"
class MyIdentifyDelegate : public chip::app::Clusters::IdentifyDelegate { /* ... */ };
// In a .cpp file:
MyIdentifyDelegate gMyIdentifyDelegate;
DefaultTimerDelegate gTimerDelegate;
chip::app::RegisteredServerCluster<chip::app::Clusters::IdentifyCluster> gIdentifyCluster(
chip::app::Clusters::IdentifyCluster::Config(1, gTimerDelegate)
.WithIdentifyType(chip::app::Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator)
.WithDelegate(&gMyIdentifyDelegate));
// In your application's init function:
#include "data-model-providers/codegen/CodegenDataModelProvider.h"
void ApplicationInit()
{
// ...
VerifyOrDie(
chip::app::CodegenDataModelProvider::Instance().Registry().Register(gIdentifyCluster.Registration()) == CHIP_NO_ERROR
);
// ...
}
Previously, you might have relied on static Identify structs or ZAP-generated
callbacks:
// This old pattern is found in `app/clusters/identify-server/identify-server.h`
// and is now considered legacy.
#include <app/clusters/identify-server/identify-server.h>
void OnIdentifyStart(::Identify *) { /* ... */ }
void OnIdentifyStop(::Identify *) { /* ... */ }
void OnTriggerEffect(::Identify * identify) { /* ... */ }
static Identify gIdentify1 = {
chip::EndpointId{ 1 }, OnIdentifyStart, OnIdentifyStop,
Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator,
OnTriggerEffect,
};
// No explicit registration was needed, as it was handled by the legacy system.