Skip to content

Commit 1dff8bc

Browse files
committed
feat(matter) adds Identification callback to all matter endpoints
1 parent a207d58 commit 1dff8bc

17 files changed

+335
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Copyright 2024 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/*
16+
* This example is the smallest code that will create a Matter Device which can be
17+
* commissioned and controlled from a Matter Environment APP.
18+
* It controls a GPIO that could be attached to a LED for visualization.
19+
* Additionally the ESP32 will send debug messages indicating the Matter activity.
20+
* Turning DEBUG Level ON may be useful to following Matter Accessory and Controller messages.
21+
*
22+
* This example is a simple Matter On/Off Light that can be controlled by a Matter Controller.
23+
* It demonstrates how to use On Identify callback when the Identify Cluster is called.
24+
* The Matter user APP can be used to request the device to identify itself by blinking the LED.
25+
*/
26+
27+
// Matter Manager
28+
#include <Matter.h>
29+
#include <WiFi.h>
30+
31+
// List of Matter Endpoints for this Node
32+
// Single On/Off Light Endpoint - at least one per node
33+
MatterOnOffLight OnOffLight;
34+
35+
// Light GPIO that can be controlled by Matter APP
36+
#ifdef LED_BUILTIN
37+
const uint8_t ledPin = LED_BUILTIN;
38+
#else
39+
const uint8_t ledPin = 2; // Set your pin here if your board has not defined LED_BUILTIN
40+
#endif
41+
42+
// set your board USER BUTTON pin here - decommissioning button
43+
const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button.
44+
45+
// Button control - decommision the Matter Node
46+
uint32_t button_time_stamp = 0; // debouncing control
47+
bool button_state = false; // false = released | true = pressed
48+
const uint32_t decommissioningTimeout = 5000; // keep the button pressed for 5s, or longer, to decommission
49+
50+
// Matter Protocol Endpoint (On/OFF Light) Callback
51+
bool matterCB(bool state) {
52+
digitalWrite(ledPin, state ? HIGH : LOW);
53+
// This callback must return the success state to Matter core
54+
return true;
55+
}
56+
57+
// WiFi is manually set and started
58+
const char *ssid = "your-ssid"; // Change this to your WiFi SSID
59+
const char *password = "your-password"; // Change this to your WiFi password
60+
61+
void setup() {
62+
// Initialize the USER BUTTON (Boot button) that will be used to decommission the Matter Node
63+
pinMode(buttonPin, INPUT_PULLUP);
64+
// Initialize the LED GPIO
65+
pinMode(ledPin, OUTPUT);
66+
67+
// Manually connect to WiFi
68+
WiFi.begin(ssid, password);
69+
// Wait for connection
70+
while (WiFi.status() != WL_CONNECTED) {
71+
delay(500);
72+
}
73+
74+
// Initialize at least one Matter EndPoint
75+
OnOffLight.begin();
76+
77+
// On Identify Callback - Blink the LED
78+
OnOffLight.onIdentify([](bool identifyIsActive, uint8_t counter) {
79+
log_i("Identify Cluster is %s, counter: %d", identifyIsActive ? "Active" : "Inactive", counter);
80+
if (identifyIsActive) {
81+
// Start Blinking the light
82+
OnOffLight.toggle();
83+
} else {
84+
// Stop Blinking and restore the light to the its last state
85+
OnOffLight.updateAccessory();
86+
}
87+
return true;
88+
});
89+
90+
// Associate a callback to the Matter Controller
91+
OnOffLight.onChange(matterCB);
92+
93+
// Matter beginning - Last step, after all EndPoints are initialized
94+
Matter.begin();
95+
96+
if (!Matter.isDeviceCommissioned()) {
97+
log_i("Matter Node is not commissioned yet.");
98+
log_i("Initiate the device discovery in your Matter environment.");
99+
log_i("Commission it to your Matter hub with the manual pairing code or QR code");
100+
log_i("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str());
101+
log_i("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str());
102+
}
103+
}
104+
105+
void loop() {
106+
// Check if the button has been pressed
107+
if (digitalRead(buttonPin) == LOW && !button_state) {
108+
// deals with button debouncing
109+
button_time_stamp = millis(); // record the time while the button is pressed.
110+
button_state = true; // pressed.
111+
}
112+
113+
if (digitalRead(buttonPin) == HIGH && button_state) {
114+
button_state = false; // released
115+
}
116+
117+
// Onboard User Button is kept pressed for longer than 5 seconds in order to decommission matter node
118+
uint32_t time_diff = millis() - button_time_stamp;
119+
if (button_state && time_diff > decommissioningTimeout) {
120+
Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again.");
121+
Matter.decommission();
122+
button_time_stamp = millis(); // avoid running decommissining again, reboot takes a second or so
123+
}
124+
125+
delay(500);
126+
}

Diff for: libraries/Matter/examples/MatterOnIdentify/ci.json

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"fqbn_append": "PartitionScheme=huge_app",
3+
"requires": [
4+
"CONFIG_SOC_WIFI_SUPPORTED=y",
5+
"CONFIG_ESP_MATTER_ENABLE_DATA_MODEL=y"
6+
]
7+
}

Diff for: libraries/Matter/src/Matter.cpp

+24-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
using namespace esp_matter;
2222
using namespace esp_matter::attribute;
2323
using namespace esp_matter::endpoint;
24+
using namespace esp_matter::identification;
2425
using namespace chip::app::Clusters;
2526

2627
constexpr auto k_timeout_seconds = 300;
@@ -67,8 +68,29 @@ static esp_err_t app_attribute_update_cb(
6768
// This callback is invoked when clients interact with the Identify Cluster.
6869
// In the callback implementation, an endpoint can identify itself. (e.g., by flashing an LED or light).
6970
static esp_err_t app_identification_cb(identification::callback_type_t type, uint16_t endpoint_id, uint8_t effect_id, uint8_t effect_variant, void *priv_data) {
70-
log_i("Identification callback: type: %u, effect: %u, variant: %u", type, effect_id, effect_variant);
71-
return ESP_OK;
71+
log_d("Identification callback to endpoint %d: type: %u, effect: %u, variant: %u", endpoint_id, effect_id, effect_variant);
72+
esp_err_t err = ESP_OK;
73+
MatterEndPoint *ep = (MatterEndPoint *)priv_data; // endpoint pointer to base class
74+
// Identify the endpoint sending a counter to the application
75+
static uint8_t counter = 0;
76+
bool identifyIsActive = false;
77+
78+
if (type == identification::callback_type_t::START) {
79+
log_v("Identification callback: START");
80+
counter = 0;
81+
identifyIsActive = true;
82+
} else if (type == identification::callback_type_t::EFFECT) {
83+
log_v("Identification callback: EFFECT");
84+
counter++;
85+
} else if (type == identification::callback_type_t::STOP) {
86+
identifyIsActive = false;
87+
log_v("Identification callback: STOP");
88+
}
89+
if (ep != NULL) {
90+
err = ep->endpointIdentifyCB(endpoint_id, identifyIsActive, counter) ? ESP_OK : ESP_FAIL;
91+
}
92+
93+
return err;
7294
}
7395

7496
// This callback is invoked for all Matter events. The application can handle the events as required.

Diff for: libraries/Matter/src/MatterEndPoint.h

+2
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ class MatterEndPoint {
102102
// this function is called by Matter internal event processor. It could be overwritten by the application, if necessary.
103103
virtual bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val) = 0;
104104

105+
// This callback is invoked when clients interact with the Identify Cluster of an specific endpoint.
106+
virtual bool endpointIdentifyCB(uint16_t endpoint_id, bool identifyIsEnabled, uint8_t identifyCounter) = 0;
105107
protected:
106108
uint16_t endpoint_id = 0;
107109
};

Diff for: libraries/Matter/src/MatterEndpoints/MatterColorLight.h

+13
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@ class MatterColorLight : public MatterEndPoint {
4646

4747
// this function is called by Matter internal event processor. It could be overwritten by the application, if necessary.
4848
bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val);
49+
// this function is invoked when clients interact with the Identify Cluster of an specific endpoint
50+
bool endpointIdentifyCB(uint16_t endpoint_id, bool identifyIsEnabled, uint8_t identifyCounter) {
51+
if (_onEndPointIdentifyCB) {
52+
return _onEndPointIdentifyCB(identifyIsEnabled, identifyCounter);
53+
}
54+
return true;
55+
}
56+
// User callaback for the Identify Cluster functionality
57+
using EndPointIdentifyCB = std::function<bool(bool, uint8_t)>;
58+
void onIdentify(EndPointIdentifyCB onEndPointIdentifyCB) {
59+
_onEndPointIdentifyCB = onEndPointIdentifyCB;
60+
}
4961

5062
// User Callback for whenever the Light On/Off state is changed by the Matter Controller
5163
using EndPointOnOffCB = std::function<bool(bool)>;
@@ -71,5 +83,6 @@ class MatterColorLight : public MatterEndPoint {
7183
EndPointOnOffCB _onChangeOnOffCB = NULL;
7284
EndPointRGBColorCB _onChangeColorCB = NULL;
7385
EndPointCB _onChangeCB = NULL;
86+
EndPointIdentifyCB _onEndPointIdentifyCB = NULL;
7487
};
7588
#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */

Diff for: libraries/Matter/src/MatterEndpoints/MatterColorTemperatureLight.h

+14
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,18 @@ class MatterColorTemperatureLight : public MatterEndPoint {
5151

5252
// this function is called by Matter internal event processor. It could be overwritten by the application, if necessary.
5353
bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val);
54+
// this function is invoked when clients interact with the Identify Cluster of an specific endpoint
55+
bool endpointIdentifyCB(uint16_t endpoint_id, bool identifyIsEnabled, uint8_t identifyCounter) {
56+
if (_onEndPointIdentifyCB) {
57+
return _onEndPointIdentifyCB(identifyIsEnabled, identifyCounter);
58+
}
59+
return true;
60+
}
61+
// User callaback for the Identify Cluster functionality
62+
using EndPointIdentifyCB = std::function<bool(bool, uint8_t)>;
63+
void onIdentify(EndPointIdentifyCB onEndPointIdentifyCB) {
64+
_onEndPointIdentifyCB = onEndPointIdentifyCB;
65+
}
5466

5567
// User Callback for whenever the Light On/Off state is changed by the Matter Controller
5668
using EndPointOnOffCB = std::function<bool(bool)>;
@@ -85,5 +97,7 @@ class MatterColorTemperatureLight : public MatterEndPoint {
8597
EndPointBrightnessCB _onChangeBrightnessCB = NULL;
8698
EndPointTemperatureCB _onChangeTemperatureCB = NULL;
8799
EndPointCB _onChangeCB = NULL;
100+
EndPointIdentifyCB _onEndPointIdentifyCB = NULL;
101+
88102
};
89103
#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */

Diff for: libraries/Matter/src/MatterEndpoints/MatterContactSensor.h

+13
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,22 @@ class MatterContactSensor : public MatterEndPoint {
4646

4747
// this function is called by Matter internal event processor. It could be overwritten by the application, if necessary.
4848
bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val);
49+
// this function is invoked when clients interact with the Identify Cluster of an specific endpoint
50+
bool endpointIdentifyCB(uint16_t endpoint_id, bool identifyIsEnabled, uint8_t identifyCounter) {
51+
if (_onEndPointIdentifyCB) {
52+
return _onEndPointIdentifyCB(identifyIsEnabled, identifyCounter);
53+
}
54+
return true;
55+
}
56+
// User callaback for the Identify Cluster functionality
57+
using EndPointIdentifyCB = std::function<bool(bool, uint8_t)>;
58+
void onIdentify(EndPointIdentifyCB onEndPointIdentifyCB) {
59+
_onEndPointIdentifyCB = onEndPointIdentifyCB;
60+
}
4961

5062
protected:
5163
bool started = false;
5264
bool contactState = false;
65+
EndPointIdentifyCB _onEndPointIdentifyCB = NULL;
5366
};
5467
#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */

Diff for: libraries/Matter/src/MatterEndpoints/MatterDimmableLight.h

+15
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,22 @@ class MatterDimmableLight : public MatterEndPoint {
4343

4444
operator bool(); // returns current on/off light state
4545
void operator=(bool state); // turns light on or off
46+
4647
// this function is called by Matter internal event processor. It could be overwritten by the application, if necessary.
4748
bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val);
49+
// this function is invoked when clients interact with the Identify Cluster of an specific endpoint
50+
bool endpointIdentifyCB(uint16_t endpoint_id, bool identifyIsEnabled, uint8_t identifyCounter) {
51+
if (_onEndPointIdentifyCB) {
52+
return _onEndPointIdentifyCB(identifyIsEnabled, identifyCounter);
53+
}
54+
return true;
55+
}
56+
// User callaback for the Identify Cluster functionality
57+
using EndPointIdentifyCB = std::function<bool(bool, uint8_t)>;
58+
void onIdentify(EndPointIdentifyCB onEndPointIdentifyCB) {
59+
_onEndPointIdentifyCB = onEndPointIdentifyCB;
60+
}
61+
4862
// User Callback for whenever the Light On/Off state is changed by the Matter Controller
4963
using EndPointOnOffCB = std::function<bool(bool)>;
5064
void onChangeOnOff(EndPointOnOffCB onChangeCB) {
@@ -69,5 +83,6 @@ class MatterDimmableLight : public MatterEndPoint {
6983
EndPointOnOffCB _onChangeOnOffCB = NULL;
7084
EndPointBrightnessCB _onChangeBrightnessCB = NULL;
7185
EndPointCB _onChangeCB = NULL;
86+
EndPointIdentifyCB _onEndPointIdentifyCB = NULL;
7287
};
7388
#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */

Diff for: libraries/Matter/src/MatterEndpoints/MatterEnhancedColorLight.h

+13
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,18 @@ class MatterEnhancedColorLight : public MatterEndPoint {
5656

5757
// this function is called by Matter internal event processor. It could be overwritten by the application, if necessary.
5858
bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val);
59+
// this function is invoked when clients interact with the Identify Cluster of an specific endpoint
60+
bool endpointIdentifyCB(uint16_t endpoint_id, bool identifyIsEnabled, uint8_t identifyCounter) {
61+
if (_onEndPointIdentifyCB) {
62+
return _onEndPointIdentifyCB(identifyIsEnabled, identifyCounter);
63+
}
64+
return true;
65+
}
66+
// User callaback for the Identify Cluster functionality
67+
using EndPointIdentifyCB = std::function<bool(bool, uint8_t)>;
68+
void onIdentify(EndPointIdentifyCB onEndPointIdentifyCB) {
69+
_onEndPointIdentifyCB = onEndPointIdentifyCB;
70+
}
5971

6072
// User Callback for whenever the Light On/Off state is changed by the Matter Controller
6173
using EndPointOnOffCB = std::function<bool(bool)>;
@@ -98,5 +110,6 @@ class MatterEnhancedColorLight : public MatterEndPoint {
98110
EndPointRGBColorCB _onChangeColorCB = NULL;
99111
EndPointTemperatureCB _onChangeTemperatureCB = NULL;
100112
EndPointCB _onChangeCB = NULL;
113+
EndPointIdentifyCB _onEndPointIdentifyCB = NULL;
101114
};
102115
#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */

Diff for: libraries/Matter/src/MatterEndpoints/MatterFan.h

+13
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,18 @@ class MatterFan : public MatterEndPoint {
105105

106106
// this function is called by Matter internal event processor. It could be overwritten by the application, if necessary.
107107
bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val);
108+
// this function is invoked when clients interact with the Identify Cluster of an specific endpoint
109+
bool endpointIdentifyCB(uint16_t endpoint_id, bool identifyIsEnabled, uint8_t identifyCounter) {
110+
if (_onEndPointIdentifyCB) {
111+
return _onEndPointIdentifyCB(identifyIsEnabled, identifyCounter);
112+
}
113+
return true;
114+
}
115+
// User callaback for the Identify Cluster functionality
116+
using EndPointIdentifyCB = std::function<bool(bool, uint8_t)>;
117+
void onIdentify(EndPointIdentifyCB onEndPointIdentifyCB) {
118+
_onEndPointIdentifyCB = onEndPointIdentifyCB;
119+
}
108120

109121
// User Callback for whenever the Fan Mode (state) is changed by the Matter Controller
110122
using EndPointModeCB = std::function<bool(FanMode_t)>;
@@ -133,6 +145,7 @@ class MatterFan : public MatterEndPoint {
133145
EndPointModeCB _onChangeModeCB = NULL;
134146
EndPointSpeedCB _onChangeSpeedCB = NULL;
135147
EndPointCB _onChangeCB = NULL;
148+
EndPointIdentifyCB _onEndPointIdentifyCB = NULL;
136149

137150
// bitmap for Fan Sequence Modes (OFF, LOW, MEDIUM, HIGH, AUTO)
138151
static const uint8_t fanSeqModeOff = 0x01;

Diff for: libraries/Matter/src/MatterEndpoints/MatterGenericSwitch.h

+13
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,21 @@ class MatterGenericSwitch : public MatterEndPoint {
3232

3333
// this function is called by Matter internal event processor. It could be overwritten by the application, if necessary.
3434
bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val);
35+
// this function is invoked when clients interact with the Identify Cluster of an specific endpoint
36+
bool endpointIdentifyCB(uint16_t endpoint_id, bool identifyIsEnabled, uint8_t identifyCounter) {
37+
if (_onEndPointIdentifyCB) {
38+
return _onEndPointIdentifyCB(identifyIsEnabled, identifyCounter);
39+
}
40+
return true;
41+
}
42+
// User callaback for the Identify Cluster functionality
43+
using EndPointIdentifyCB = std::function<bool(bool, uint8_t)>;
44+
void onIdentify(EndPointIdentifyCB onEndPointIdentifyCB) {
45+
_onEndPointIdentifyCB = onEndPointIdentifyCB;
46+
}
3547

3648
protected:
3749
bool started = false;
50+
EndPointIdentifyCB _onEndPointIdentifyCB = NULL;
3851
};
3952
#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */

Diff for: libraries/Matter/src/MatterEndpoints/MatterHumiditySensor.h

+13
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,18 @@ class MatterHumiditySensor : public MatterEndPoint {
5757

5858
// this function is called by Matter internal event processor. It could be overwritten by the application, if necessary.
5959
bool attributeChangeCB(uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val);
60+
// this function is invoked when clients interact with the Identify Cluster of an specific endpoint
61+
bool endpointIdentifyCB(uint16_t endpoint_id, bool identifyIsEnabled, uint8_t identifyCounter) {
62+
if (_onEndPointIdentifyCB) {
63+
return _onEndPointIdentifyCB(identifyIsEnabled, identifyCounter);
64+
}
65+
return true;
66+
}
67+
// User callaback for the Identify Cluster functionality
68+
using EndPointIdentifyCB = std::function<bool(bool, uint8_t)>;
69+
void onIdentify(EndPointIdentifyCB onEndPointIdentifyCB) {
70+
_onEndPointIdentifyCB = onEndPointIdentifyCB;
71+
}
6072

6173
protected:
6274
bool started = false;
@@ -65,5 +77,6 @@ class MatterHumiditySensor : public MatterEndPoint {
6577
// internal function to set the raw humidity value (Matter Cluster)
6678
bool begin(uint16_t _rawHumidity);
6779
bool setRawHumidity(uint16_t _rawHumidity);
80+
EndPointIdentifyCB _onEndPointIdentifyCB = NULL;
6881
};
6982
#endif /* CONFIG_ESP_MATTER_ENABLE_DATA_MODEL */

0 commit comments

Comments
 (0)