Skip to content

Commit 69825a9

Browse files
feat(Matter): New Matter Endpoint - Dimmable Light (#10543)
* feat(matter): source code folder organization * feat(matter): new matter endpoint dimmable light * feat(matter): dimmable friend class and adjusts log levels * feat(matter): adds new folder and source code to cmakelists.txt * fix(matter): identation in cmakelists.txt * feat(matter): adds license disclaimer to all source code * feat(matter): example code simplification * feat(matter): make it work with rgb and analog led * feat(matter): single user callback based on lambda function * feat(matter): commentaries and code improvement. update() and callbacks added. * feat(matter): adde new keywords to arduino settings * feat(matter): example code adjustment to use improved api * fix(matter): it shuold work even when no callback is set * feat(matter): matter.h includes all possible endpoint header files * feat(matter): adjusts all examples to only include matter.h * fix(matter): double declaration of ret - var scope issue * ci(pre-commit): Apply automatic fixes --------- Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
1 parent a80b03e commit 69825a9

File tree

14 files changed

+609
-35
lines changed

14 files changed

+609
-35
lines changed

Diff for: CMakeLists.txt

+2-1
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ set(ARDUINO_LIBRARY_OpenThread_SRCS
169169
libraries/OpenThread/src/OThreadCLI_Util.cpp)
170170

171171
set(ARDUINO_LIBRARY_Matter_SRCS
172-
libraries/Matter/src/MatterOnOffLight.cpp
172+
libraries/Matter/src/MatterEndpoints/MatterOnOffLight.cpp
173+
libraries/Matter/src/MatterEndpoints/MatterDimmableLight.cpp
173174
libraries/Matter/src/Matter.cpp)
174175

175176
set(ARDUINO_LIBRARY_PPP_SRCS

Diff for: libraries/Matter/examples/MatterCommissionTest/MatterCommissionTest.ino

+14-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
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+
115
// Matter Manager
216
#include <Matter.h>
317
#include <WiFi.h>
418

519
// List of Matter Endpoints for this Node
620
// On/Off Light Endpoint
7-
#include <MatterOnOffLight.h>
821
MatterOnOffLight OnOffLight;
922

1023
// WiFi is manually set and started

Diff for: libraries/Matter/examples/MatterComposedLights/MatterComposedLights.ino

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
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+
115
// Matter Manager
216
#include <Matter.h>
317
#include <WiFi.h>
418

519
// List of Matter Endpoints for this Node
620
// There will be 3 On/Off Light Endpoints in the same Node
7-
#include <MatterOnOffLight.h>
821
MatterOnOffLight OnOffLight1;
922
MatterOnOffLight OnOffLight2;
1023
MatterOnOffLight OnOffLight3;
@@ -56,9 +69,9 @@ void setup() {
5669
OnOffLight1.begin();
5770
OnOffLight2.begin();
5871
OnOffLight3.begin();
59-
OnOffLight1.onChangeOnOff(setLightOnOff1);
60-
OnOffLight2.onChangeOnOff(setLightOnOff2);
61-
OnOffLight3.onChangeOnOff(setLightOnOff3);
72+
OnOffLight1.onChange(setLightOnOff1);
73+
OnOffLight2.onChange(setLightOnOff2);
74+
OnOffLight3.onChange(setLightOnOff3);
6275

6376
// Matter beginning - Last step, after all EndPoints are initialized
6477
Matter.begin();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
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+
// Matter Manager
16+
#include <Matter.h>
17+
#include <WiFi.h>
18+
#include <Preferences.h>
19+
20+
// List of Matter Endpoints for this Node
21+
// Dimmable Light Endpoint
22+
MatterDimmableLight DimmableLight;
23+
24+
// it will keep last OnOff & Brightness state stored, using Preferences
25+
Preferences lastStatePref;
26+
27+
// set your board RGB LED pin here
28+
#ifdef RGB_BUILTIN
29+
const uint8_t ledPin = RGB_BUILTIN;
30+
#else
31+
const uint8_t ledPin = 2; // Set your pin here if your board has not defined LED_BUILTIN
32+
#warning "Do not forget to set the RGB LED pin"
33+
#endif
34+
35+
// set your board USER BUTTON pin here
36+
const uint8_t buttonPin = 0; // Set your pin here. Using BOOT Button. C6/C3 use GPIO9.
37+
38+
// WiFi is manually set and started
39+
const char *ssid = "your-ssid"; // Change this to your WiFi SSID
40+
const char *password = "your-password"; // Change this to your WiFi password
41+
42+
// Set the RGB LED Light based on the current state of the Dimmable Light
43+
bool setLightState(bool state, uint8_t brightness) {
44+
if (state) {
45+
#ifdef RGB_BUILTIN
46+
rgbLedWrite(ledPin, brightness, brightness, brightness);
47+
#else
48+
analogWrite(ledPin, brightness);
49+
#endif
50+
} else {
51+
digitalWrite(ledPin, LOW);
52+
}
53+
// store last Brightness and OnOff state for when the Light is restarted / power goes off
54+
lastStatePref.putUChar("lastBrightness", brightness);
55+
lastStatePref.putBool("lastOnOffState", state);
56+
// This callback must return the success state to Matter core
57+
return true;
58+
}
59+
60+
void setup() {
61+
// Initialize the USER BUTTON (Boot button) GPIO that will act as a toggle switch
62+
pinMode(buttonPin, INPUT_PULLUP);
63+
// Initialize the LED (light) GPIO and Matter End Point
64+
pinMode(ledPin, OUTPUT);
65+
66+
Serial.begin(115200);
67+
while (!Serial) {
68+
delay(100);
69+
}
70+
71+
// We start by connecting to a WiFi network
72+
Serial.print("Connecting to ");
73+
Serial.println(ssid);
74+
// enable IPv6
75+
WiFi.enableIPv6(true);
76+
// Manually connect to WiFi
77+
WiFi.begin(ssid, password);
78+
// Wait for connection
79+
while (WiFi.status() != WL_CONNECTED) {
80+
delay(500);
81+
Serial.print(".");
82+
}
83+
Serial.println("\r\nWiFi connected");
84+
Serial.println("IP address: ");
85+
Serial.println(WiFi.localIP());
86+
delay(500);
87+
88+
// Initialize Matter EndPoint
89+
lastStatePref.begin("matterLight", false);
90+
// default OnOff state is ON if not stored before
91+
bool lastOnOffState = lastStatePref.getBool("lastOnOffState", true);
92+
// default brightness ~= 6% (15/255)
93+
uint8_t lastBrightness = lastStatePref.getUChar("lastBrightness", 15);
94+
DimmableLight.begin(lastOnOffState, lastBrightness);
95+
// set the callback function to handle the Light state change
96+
DimmableLight.onChange(setLightState);
97+
98+
// lambda functions are used to set the attribute change callbacks
99+
DimmableLight.onChangeOnOff([](bool state) {
100+
Serial.printf("Light OnOff changed to %s\r\n", state ? "ON" : "OFF");
101+
return true;
102+
});
103+
DimmableLight.onChangeBrightness([](uint8_t level) {
104+
Serial.printf("Light Brightness changed to %d\r\n", level);
105+
return true;
106+
});
107+
108+
// Matter beginning - Last step, after all EndPoints are initialized
109+
Matter.begin();
110+
// This may be a restart of a already commissioned Matter accessory
111+
if (Matter.isDeviceCommissioned()) {
112+
Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use.");
113+
Serial.printf("Initial state: %s | brightness: %d\r\n", DimmableLight ? "ON" : "OFF", DimmableLight.getBrightness());
114+
// configure the Light based on initial on-off state and brightness
115+
DimmableLight.updateAccessory();
116+
}
117+
}
118+
// Button control
119+
uint32_t button_time_stamp = 0; // debouncing control
120+
bool button_state = false; // false = released | true = pressed
121+
const uint32_t debouceTime = 250; // button debouncing time (ms)
122+
const uint32_t decommissioningTimeout = 10000; // keep the button pressed for 10s to decommission the light
123+
124+
void loop() {
125+
// Check Matter Light Commissioning state, which may change during execution of loop()
126+
if (!Matter.isDeviceCommissioned()) {
127+
Serial.println("");
128+
Serial.println("Matter Node is not commissioned yet.");
129+
Serial.println("Initiate the device discovery in your Matter environment.");
130+
Serial.println("Commission it to your Matter hub with the manual pairing code or QR code");
131+
Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str());
132+
Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str());
133+
// waits for Matter Light Commissioning.
134+
uint32_t timeCount = 0;
135+
while (!Matter.isDeviceCommissioned()) {
136+
delay(100);
137+
if ((timeCount++ % 50) == 0) { // 50*100ms = 5 sec
138+
Serial.println("Matter Node not commissioned yet. Waiting for commissioning.");
139+
}
140+
}
141+
Serial.printf("Initial state: %s | brightness: %d\r\n", DimmableLight ? "ON" : "OFF", DimmableLight.getBrightness());
142+
// configure the Light based on initial on-off state and brightness
143+
DimmableLight.updateAccessory();
144+
Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use.");
145+
}
146+
147+
// A button is also used to control the light
148+
// Check if the button has been pressed
149+
if (digitalRead(buttonPin) == LOW && !button_state) {
150+
// deals with button debouncing
151+
button_time_stamp = millis(); // record the time while the button is pressed.
152+
button_state = true; // pressed.
153+
}
154+
155+
// Onboard User Button is used as a Light toggle switch or to decommission it
156+
uint32_t time_diff = millis() - button_time_stamp;
157+
if (button_state && time_diff > debouceTime && digitalRead(buttonPin) == HIGH) {
158+
button_state = false; // released
159+
// Toggle button is released - toggle the light
160+
Serial.println("User button released. Toggling Light!");
161+
DimmableLight.toggle(); // Matter Controller also can see the change
162+
163+
// Factory reset is triggered if the button is pressed longer than 10 seconds
164+
if (time_diff > decommissioningTimeout) {
165+
Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again.");
166+
DimmableLight = false; // turn the light off
167+
Matter.decommission();
168+
}
169+
}
170+
}
+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/examples/MatterOnOffLight/MatterOnOffLight.ino

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
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+
115
// Matter Manager
216
#include <Matter.h>
317
#include <WiFi.h>
418
#include <Preferences.h>
519

620
// List of Matter Endpoints for this Node
721
// On/Off Light Endpoint
8-
#include <MatterOnOffLight.h>
922
MatterOnOffLight OnOffLight;
1023

1124
// it will keep last OnOff state stored, using Preferences
@@ -72,15 +85,15 @@ void setup() {
7285
lastStatePref.begin("matterLight", false);
7386
bool lastOnOffState = lastStatePref.getBool("lastOnOffState", true);
7487
OnOffLight.begin(lastOnOffState);
75-
OnOffLight.onChangeOnOff(setLightOnOff);
88+
OnOffLight.onChange(setLightOnOff);
7689

7790
// Matter beginning - Last step, after all EndPoints are initialized
7891
Matter.begin();
7992
// This may be a restart of a already commissioned Matter accessory
8093
if (Matter.isDeviceCommissioned()) {
8194
Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use.");
8295
Serial.printf("Initial state: %s\r\n", OnOffLight.getOnOff() ? "ON" : "OFF");
83-
setLightOnOff(OnOffLight.getOnOff()); // configure the Light based on initial state
96+
OnOffLight.updateAccessory(); // configure the Light based on initial state
8497
}
8598
}
8699
// Button control
@@ -107,7 +120,7 @@ void loop() {
107120
}
108121
}
109122
Serial.printf("Initial state: %s\r\n", OnOffLight.getOnOff() ? "ON" : "OFF");
110-
setLightOnOff(OnOffLight.getOnOff()); // configure the Light based on initial state
123+
OnOffLight.updateAccessory(); // configure the Light based on initial state
111124
Serial.println("Matter Node is commissioned and connected to Wi-Fi. Ready for use.");
112125
}
113126

Diff for: libraries/Matter/keywords.txt

+7-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
#######################################
88

99
Matter KEYWORD1
10+
ArduinoMatter KEYWORD1
1011
MatterOnOffLight KEYWORD1
12+
MatterDimmableLight KEYWORD1
1113
MatterEndPoint KEYWORD1
1214

1315
#######################################
@@ -16,7 +18,6 @@ MatterEndPoint KEYWORD1
1618

1719
begin KEYWORD2
1820
end KEYWORD2
19-
start KEYWORD2
2021
getManualPairingCode KEYWORD2
2122
getOnboardingQRCodeUrl KEYWORD2
2223
isDeviceCommissioned KEYWORD2
@@ -27,8 +28,13 @@ decommission KEYWORD2
2728
attributeChangeCB KEYWORD2
2829
setOnOff KEYWORD2
2930
getOnOff KEYWORD2
31+
setBrightness KEYWORD2
32+
getBrightness KEYWORD2
3033
toggle KEYWORD2
34+
updateAccessory KEYWORD2
35+
onChange KEYWORD2
3136
onChangeOnOff KEYWORD2
37+
onChangeBrightness KEYWORD2
3238

3339
#######################################
3440
# Constants (LITERAL1)

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

+21-6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
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+
115
#include <sdkconfig.h>
216
#ifdef CONFIG_ESP_MATTER_ENABLE_DATA_MODEL
317

@@ -27,25 +41,26 @@ esp_err_t matter_light_attribute_update(
2741
static esp_err_t app_attribute_update_cb(
2842
attribute::callback_type_t type, uint16_t endpoint_id, uint32_t cluster_id, uint32_t attribute_id, esp_matter_attr_val_t *val, void *priv_data
2943
) {
44+
log_d("Attribute update callback: type: %u, endpoint: %u, cluster: %u, attribute: %u, val: %u", type, endpoint_id, cluster_id, attribute_id, val->val.u32);
3045
esp_err_t err = ESP_OK;
3146
MatterEndPoint *ep = (MatterEndPoint *)priv_data; // endpoint pointer to base class
3247
switch (type) {
3348
case PRE_UPDATE: // Callback before updating the value in the database
34-
log_i("Attribute update callback: PRE_UPDATE");
49+
log_v("Attribute update callback: PRE_UPDATE");
3550
if (ep != NULL) {
3651
err = ep->attributeChangeCB(endpoint_id, cluster_id, attribute_id, val) ? ESP_OK : ESP_FAIL;
3752
}
3853
break;
3954
case POST_UPDATE: // Callback after updating the value in the database
40-
log_i("Attribute update callback: POST_UPDATE");
55+
log_v("Attribute update callback: POST_UPDATE");
4156
break;
4257
case READ: // Callback for reading the attribute value. This is used when the `ATTRIBUTE_FLAG_OVERRIDE` is set.
43-
log_i("Attribute update callback: READ");
58+
log_v("Attribute update callback: READ");
4459
break;
4560
case WRITE: // Callback for writing the attribute value. This is used when the `ATTRIBUTE_FLAG_OVERRIDE` is set.
46-
log_i("Attribute update callback: WRITE");
61+
log_v("Attribute update callback: WRITE");
4762
break;
48-
default: log_i("Attribute update callback: Unknown type %d", type);
63+
default: log_v("Attribute update callback: Unknown type %d", type);
4964
}
5065
return err;
5166
}
@@ -114,7 +129,7 @@ void ArduinoMatter::_init() {
114129

115130
void ArduinoMatter::begin() {
116131
if (!_matter_has_started) {
117-
log_w("No Matter endpoint has been created. Please create an endpoint first.");
132+
log_e("No Matter endpoint has been created. Please create an endpoint first.");
118133
return;
119134
}
120135

0 commit comments

Comments
 (0)