File tree

6 files changed

+369
-28
lines changed

6 files changed

+369
-28
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
// Copyright 2025 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+
19+
// WiFi is manually set and started
20+
const char *ssid = "your-ssid"; // Change this to your WiFi SSID
21+
const char *password = "your-password"; // Change this to your WiFi password
22+
23+
// List of Matter Endpoints for this Node
24+
// On/Off Light Endpoint
25+
MatterOnOffLight OnOffLight;
26+
27+
// This function is called when a Matter event occurs
28+
void onMatterEvent(matterEvent_t eventType, const chip::DeviceLayer::ChipDeviceEvent *eventInfo) {
29+
// Print the event type to Serial
30+
Serial.print("===> Got a Matter Event: ");
31+
switch (eventType) {
32+
case MATTER_WIFI_CONNECTIVITY_CHANGE: Serial.println("WiFi Connectivity Change"); break;
33+
case MATTER_THREAD_CONNECTIVITY_CHANGE: Serial.println("Thread Connectivity Change"); break;
34+
case MATTER_INTERNET_CONNECTIVITY_CHANGE:
35+
{
36+
bool newIPAddress = false;
37+
Serial.print("Internet Connectivity Change :: ");
38+
if (eventInfo->InternetConnectivityChange.IPv4 != chip::DeviceLayer::ConnectivityChange::kConnectivity_NoChange) {
39+
Serial.print("IPv4 Connectivity: ");
40+
switch (eventInfo->InternetConnectivityChange.IPv4) {
41+
case chip::DeviceLayer::ConnectivityChange::kConnectivity_Established:
42+
{
43+
newIPAddress = true;
44+
break;
45+
}
46+
case chip::DeviceLayer::ConnectivityChange::kConnectivity_Lost: Serial.println("Lost"); break;
47+
default: Serial.println("Unknown"); break;
48+
}
49+
}
50+
if (eventInfo->InternetConnectivityChange.IPv6 != chip::DeviceLayer::ConnectivityChange::kConnectivity_NoChange) {
51+
Serial.print("IPv6 Connectivity: ");
52+
switch (eventInfo->InternetConnectivityChange.IPv6) {
53+
case chip::DeviceLayer::ConnectivityChange::kConnectivity_Established:
54+
{
55+
newIPAddress = true;
56+
break;
57+
}
58+
case chip::DeviceLayer::ConnectivityChange::kConnectivity_Lost: Serial.println("Lost"); break;
59+
default: Serial.println("Unknown"); break;
60+
}
61+
}
62+
// Print the IP address if it was established
63+
if (newIPAddress) {
64+
Serial.print("Established - IP Address: ");
65+
char ipAddressStr[chip::Transport::PeerAddress::kMaxToStringSize];
66+
eventInfo->InternetConnectivityChange.ipAddress.ToString(ipAddressStr);
67+
Serial.println(ipAddressStr);
68+
}
69+
break;
70+
}
71+
case MATTER_SERVICE_CONNECTIVITY_CHANGE: Serial.println("Service Connectivity Change"); break;
72+
case MATTER_SERVICE_PROVISIONING_CHANGE: Serial.println("Service Provisioning Change"); break;
73+
case MATTER_TIME_SYNC_CHANGE: Serial.println("Time Sync Change"); break;
74+
case MATTER_CHIPOBLE_CONNECTION_ESTABLISHED: Serial.println("CHIPoBLE Connection Established"); break;
75+
case MATTER_CHIPOBLE_CONNECTION_CLOSED: Serial.println("CHIPoBLE Connection Closed"); break;
76+
case MATTER_CLOSE_ALL_BLE_CONNECTIONS: Serial.println("Close All BLE Connections"); break;
77+
case MATTER_WIFI_DEVICE_AVAILABLE: Serial.println("WiFi Device Available"); break;
78+
case MATTER_OPERATIONAL_NETWORK_STARTED: Serial.println("Operational Network Started"); break;
79+
case MATTER_THREAD_STATE_CHANGE: Serial.println("Thread State Change"); break;
80+
case MATTER_THREAD_INTERFACE_STATE_CHANGE: Serial.println("Thread Interface State Change"); break;
81+
case MATTER_CHIPOBLE_ADVERTISING_CHANGE: Serial.println("CHIPoBLE Advertising Change"); break;
82+
case MATTER_INTERFACE_IP_ADDRESS_CHANGED:
83+
switch (eventInfo->InterfaceIpAddressChanged.Type) {
84+
case chip::DeviceLayer::InterfaceIpChangeType::kIpV4_Assigned: Serial.println("IPv4 Address Assigned"); break;
85+
case chip::DeviceLayer::InterfaceIpChangeType::kIpV4_Lost: Serial.println("IPv4 Address Lost"); break;
86+
case chip::DeviceLayer::InterfaceIpChangeType::kIpV6_Assigned: Serial.println("IPv6 Address Assigned"); break;
87+
case chip::DeviceLayer::InterfaceIpChangeType::kIpV6_Lost: Serial.println("IPv6 Address Lost"); break;
88+
}
89+
break;
90+
case MATTER_COMMISSIONING_COMPLETE: Serial.println("Commissioning Complete"); break;
91+
case MATTER_FAIL_SAFE_TIMER_EXPIRED: Serial.println("Fail Safe Timer Expired"); break;
92+
case MATTER_OPERATIONAL_NETWORK_ENABLED: Serial.println("Operational Network Enabled"); break;
93+
case MATTER_DNSSD_INITIALIZED: Serial.println("DNS-SD Initialized"); break;
94+
case MATTER_DNSSD_RESTART_NEEDED: Serial.println("DNS-SD Restart Needed"); break;
95+
case MATTER_BINDINGS_CHANGED_VIA_CLUSTER: Serial.println("Bindings Changed Via Cluster"); break;
96+
case MATTER_OTA_STATE_CHANGED: Serial.println("OTA State Changed"); break;
97+
case MATTER_SERVER_READY: Serial.println("Server Ready"); break;
98+
case MATTER_BLE_DEINITIALIZED: Serial.println("BLE Deinitialized"); break;
99+
case MATTER_COMMISSIONING_SESSION_STARTED: Serial.println("Commissioning Session Started"); break;
100+
case MATTER_COMMISSIONING_SESSION_STOPPED: Serial.println("Commissioning Session Stopped"); break;
101+
case MATTER_COMMISSIONING_WINDOW_OPEN: Serial.println("Commissioning Window Opened"); break;
102+
case MATTER_COMMISSIONING_WINDOW_CLOSED: Serial.println("Commissioning Window Closed"); break;
103+
case MATTER_FABRIC_WILL_BE_REMOVED: Serial.println("Fabric Will Be Removed"); break;
104+
case MATTER_FABRIC_REMOVED: Serial.println("Fabric Removed"); break;
105+
case MATTER_FABRIC_COMMITTED: Serial.println("Fabric Committed"); break;
106+
case MATTER_FABRIC_UPDATED: Serial.println("Fabric Updated"); break;
107+
case MATTER_ESP32_SPECIFIC_EVENT: Serial.println("Sending ESP32 Platform Specific Events"); break;
108+
case MATTER_ESP32_PUBLIC_SPECIFIC_EVENT: Serial.println("Next Event Has Populated EventInfo"); break;
109+
default:
110+
// If the event type is not recognized, print "Unknown" and the event ID
111+
Serial.println("Unknown, EventID = 0x" + String(eventType, HEX));
112+
break;
113+
}
114+
}
115+
116+
void setup() {
117+
Serial.begin(115200);
118+
while (!Serial) {
119+
delay(10); // Wait for Serial to initialize
120+
}
121+
122+
// We start by connecting to a WiFi network
123+
Serial.print("Connecting to ");
124+
Serial.println(ssid);
125+
// Manually connect to WiFi
126+
WiFi.enableIPv6(true); // Enable IPv6 if needed
127+
WiFi.begin(ssid, password);
128+
// Wait for connection
129+
while (WiFi.status() != WL_CONNECTED) {
130+
delay(500);
131+
Serial.print(".");
132+
}
133+
Serial.println("\r\nWiFi connected");
134+
Serial.println("IP address: ");
135+
Serial.println(WiFi.localIP());
136+
delay(500);
137+
138+
// Initialize at least one Matter EndPoint
139+
OnOffLight.begin();
140+
141+
// Set the Matter Event Callback
142+
Matter.onEvent(onMatterEvent);
143+
// Matter beginning - Last step, after all EndPoints are initialized
144+
Matter.begin();
145+
Serial.println("Starting Matter Commission Test...");
146+
}
147+
148+
void loop() {
149+
// Check Matter Commissioning state
150+
if (!Matter.isDeviceCommissioned()) {
151+
Serial.println("");
152+
Serial.println("Matter Node is not commissioned yet.");
153+
Serial.println("Initiate the device discovery in your Matter environment.");
154+
Serial.println("Commission it to your Matter hub with the manual pairing code or QR code");
155+
Serial.printf("Manual pairing code: %s\r\n", Matter.getManualPairingCode().c_str());
156+
Serial.printf("QR code URL: %s\r\n", Matter.getOnboardingQRCodeUrl().c_str());
157+
// waits for Matter Light Commissioning.
158+
while (!Matter.isDeviceCommissioned()) {
159+
delay(5000);
160+
Serial.println("Matter Fabric not commissioned yet. Waiting for commissioning.");
161+
}
162+
}
163+
Serial.println("Matter Node is commissioned and connected to Wi-Fi.");
164+
Serial.println("====> Decommissioning in 60 seconds. <====");
165+
delay(60000);
166+
Matter.decommission();
167+
Serial.println("Matter Node is decommissioned. Commissioning widget shall start over.");
168+
}
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+
}
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ EndPointSpeedCB KEYWORD1
3636
EndPointOnOffCB KEYWORD1
3737
EndPointBrightnessCB KEYWORD1
3838
EndPointRGBColorCB KEYWORD1
39+
matterEvent_t KEYWORD1
40+
matterEventCB KEYWORD1
3941

4042
#######################################
4143
# Methods and Functions (KEYWORD2)
@@ -108,6 +110,7 @@ onChangeMode KEYWORD2
108110
onChangeLocalTemperature KEYWORD2
109111
onChangeCoolingSetpoint KEYWORD2
110112
onChangeHeatingSetpoint KEYWORD2
113+
onEvent KEYWORD2
111114

112115
#######################################
113116
# Constants (LITERAL1)
@@ -144,5 +147,37 @@ THERMOSTAT_MODE_OFF LITERAL1
144147
THERMOSTAT_MODE_AUTO LITERAL1
145148
THERMOSTAT_MODE_COOL LITERAL1
146149
THERMOSTAT_MODE_HEAT LITERAL1
147-
THERMOSTAT_AUTO_MODE_DISABLED LITERAL1
148-
THERMOSTAT_AUTO_MODE_ENABLED LITERAL1
150+
MATTER_WIFI_CONNECTIVITY_CHANGE LITERAL1
151+
MATTER_THREAD_CONNECTIVITY_CHANGE LITERAL1
152+
MATTER_INTERNET_CONNECTIVITY_CHANGE LITERAL1
153+
MATTER_SERVICE_CONNECTIVITY_CHANGE LITERAL1
154+
MATTER_SERVICE_PROVISIONING_CHANGE LITERAL1
155+
MATTER_TIME_SYNC_CHANGE LITERAL1
156+
MATTER_CHIPOBLE_CONNECTION_ESTABLISHED LITERAL1
157+
MATTER_CHIPOBLE_CONNECTION_CLOSED LITERAL1
158+
MATTER_CLOSE_ALL_BLE_CONNECTIONS LITERAL1
159+
MATTER_WIFI_DEVICE_AVAILABLE LITERAL1
160+
MATTER_OPERATIONAL_NETWORK_STARTED LITERAL1
161+
MATTER_THREAD_STATE_CHANGE LITERAL1
162+
MATTER_THREAD_INTERFACE_STATE_CHANGE LITERAL1
163+
MATTER_CHIPOBLE_ADVERTISING_CHANGE LITERAL1
164+
MATTER_INTERFACE_IP_ADDRESS_CHANGED LITERAL1
165+
MATTER_COMMISSIONING_COMPLETE LITERAL1
166+
MATTER_FAIL_SAFE_TIMER_EXPIRED LITERAL1
167+
MATTER_OPERATIONAL_NETWORK_ENABLED LITERAL1
168+
MATTER_DNSSD_INITIALIZED LITERAL1
169+
MATTER_DNSSD_RESTART_NEEDED LITERAL1
170+
MATTER_BINDINGS_CHANGED_VIA_CLUSTER LITERAL1
171+
MATTER_OTA_STATE_CHANGED LITERAL1
172+
MATTER_SERVER_READY LITERAL1
173+
MATTER_BLE_DEINITIALIZED LITERAL1
174+
MATTER_ESP32_SPECIFIC_EVENT LITERAL1
175+
MATTER_COMMISSIONING_SESSION_STARTED LITERAL1
176+
MATTER_COMMISSIONING_SESSION_STOPPED LITERAL1
177+
MATTER_COMMISSIONING_WINDOW_OPEN LITERAL1
178+
MATTER_COMMISSIONING_WINDOW_CLOSED LITERAL1
179+
MATTER_FABRIC_WILL_BE_REMOVED LITERAL1
180+
MATTER_FABRIC_REMOVED LITERAL1
181+
MATTER_FABRIC_COMMITTED LITERAL1
182+
MATTER_FABRIC_UPDATED LITERAL1
183+
MATTER_ESP32_PUBLIC_SPECIFIC_EVENT LITERAL1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ constexpr auto k_timeout_seconds = 300;
2828

2929
static bool _matter_has_started = false;
3030
static node::config_t node_config;
31-
static node_t *deviceNode = NULL;
31+
static node_t *deviceNode = nullptr;
32+
ArduinoMatter::matterEventCB ArduinoMatter::_matterEventCB = nullptr;
3233

3334
// This callback is called for every attribute update. The callback implementation shall
3435
// handle the desired attributes and return an appropriate error code. If the attribute
@@ -42,7 +43,7 @@ static esp_err_t app_attribute_update_cb(
4243
switch (type) {
4344
case PRE_UPDATE: // Callback before updating the value in the database
4445
log_v("Attribute update callback: PRE_UPDATE");
45-
if (ep != NULL) {
46+
if (ep != nullptr) {
4647
err = ep->attributeChangeCB(endpoint_id, cluster_id, attribute_id, val) ? ESP_OK : ESP_FAIL;
4748
}
4849
break;
@@ -78,7 +79,7 @@ static esp_err_t app_identification_cb(identification::callback_type_t type, uin
7879
identifyIsActive = false;
7980
log_v("Identification callback: STOP");
8081
}
81-
if (ep != NULL) {
82+
if (ep != nullptr) {
8283
err = ep->endpointIdentifyCB(endpoint_id, identifyIsActive) ? ESP_OK : ESP_FAIL;
8384
}
8485

@@ -89,21 +90,21 @@ static esp_err_t app_identification_cb(identification::callback_type_t type, uin
8990
static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) {
9091
switch (event->Type) {
9192
case chip::DeviceLayer::DeviceEventType::kInterfaceIpAddressChanged:
92-
log_i(
93+
log_d(
9394
"Interface %s Address changed", event->InterfaceIpAddressChanged.Type == chip::DeviceLayer::InterfaceIpChangeType::kIpV4_Assigned ? "IPv4" : "IPV6"
9495
);
9596
break;
96-
case chip::DeviceLayer::DeviceEventType::kCommissioningComplete: log_i("Commissioning complete"); break;
97-
case chip::DeviceLayer::DeviceEventType::kFailSafeTimerExpired: log_i("Commissioning failed, fail safe timer expired"); break;
98-
case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStarted: log_i("Commissioning session started"); break;
99-
case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStopped: log_i("Commissioning session stopped"); break;
100-
case chip::DeviceLayer::DeviceEventType::kCommissioningWindowOpened: log_i("Commissioning window opened"); break;
101-
case chip::DeviceLayer::DeviceEventType::kCommissioningWindowClosed: log_i("Commissioning window closed"); break;
97+
case chip::DeviceLayer::DeviceEventType::kCommissioningComplete: log_d("Commissioning complete"); break;
98+
case chip::DeviceLayer::DeviceEventType::kFailSafeTimerExpired: log_d("Commissioning failed, fail safe timer expired"); break;
99+
case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStarted: log_d("Commissioning session started"); break;
100+
case chip::DeviceLayer::DeviceEventType::kCommissioningSessionStopped: log_d("Commissioning session stopped"); break;
101+
case chip::DeviceLayer::DeviceEventType::kCommissioningWindowOpened: log_d("Commissioning window opened"); break;
102+
case chip::DeviceLayer::DeviceEventType::kCommissioningWindowClosed: log_d("Commissioning window closed"); break;
102103
case chip::DeviceLayer::DeviceEventType::kFabricRemoved:
103104
{
104-
log_i("Fabric removed successfully");
105+
log_d("Fabric removed successfully");
105106
if (chip::Server::GetInstance().GetFabricTable().FabricCount() == 0) {
106-
log_i("No fabric left, opening commissioning window");
107+
log_d("No fabric left, opening commissioning window");
107108
chip::CommissioningWindowManager &commissionMgr = chip::Server::GetInstance().GetCommissioningWindowManager();
108109
constexpr auto kTimeoutSeconds = chip::System::Clock::Seconds16(k_timeout_seconds);
109110
if (!commissionMgr.IsCommissioningWindowOpen()) {
@@ -116,12 +117,16 @@ static void app_event_cb(const ChipDeviceEvent *event, intptr_t arg) {
116117
}
117118
break;
118119
}
119-
case chip::DeviceLayer::DeviceEventType::kFabricWillBeRemoved: log_i("Fabric will be removed"); break;
120-
case chip::DeviceLayer::DeviceEventType::kFabricUpdated: log_i("Fabric is updated"); break;
121-
case chip::DeviceLayer::DeviceEventType::kFabricCommitted: log_i("Fabric is committed"); break;
122-
case chip::DeviceLayer::DeviceEventType::kBLEDeinitialized: log_i("BLE deinitialized and memory reclaimed"); break;
120+
case chip::DeviceLayer::DeviceEventType::kFabricWillBeRemoved: log_d("Fabric will be removed"); break;
121+
case chip::DeviceLayer::DeviceEventType::kFabricUpdated: log_d("Fabric is updated"); break;
122+
case chip::DeviceLayer::DeviceEventType::kFabricCommitted: log_d("Fabric is committed"); break;
123+
case chip::DeviceLayer::DeviceEventType::kBLEDeinitialized: log_d("BLE deinitialized and memory reclaimed"); break;
123124
default: break;
124125
}
126+
// Check if the user-defined callback is set
127+
if (ArduinoMatter::_matterEventCB != nullptr) {
128+
ArduinoMatter::_matterEventCB(static_cast<matterEvent_t>(event->Type), event);
129+
}
125130
}
126131

127132
void ArduinoMatter::_init() {

0 commit comments

Comments
 (0)