This guide shows you how to create a Matter compatible on/off light device that controls an ESP32 GPIO programmed using Arduino IDE. The device can be commissioned into Apple Home, Google Home, Amazon Alexa, Home Assistant, or other Matter controllers. It supports local button control, light state persistence after a reboot, and factory reset (decommissioning).

Prerequisites
Before proceeding with this tutorial, you should have the ESP32 boards installed in your Arduino IDE:
You will also need an ESP32 development board model of your choice and an Home Automation controller like Amazon Echo Dot Max (Alexa).
Matter Protocol Introduction
Matter formerly known as Project CHIP (Connected Home over IP) is an open-source and industry standard connectivity protocol for smart home devices. Matter protocol was developed by the Connectivity Standards Alliance (CSA) with contributions from major companies including Apple, Google, Amazon, Samsung, and others. Matter aims to solve the fragmentation problem where each company builds their own proprietary protocol to interact with their devices.

Key features of Matter protocol:
- Interoperability: devices from different manufacturers work together seamlessly in the same ecosystem (Apple Home, Google Home, Amazon Alexa, Home Assistant, Samsung SmartThings, etc…).
- Local control: communication happens primarily on the local network (Wi-Fi, Thread, or Ethernet). The cloud connectivity is optional.
- Security: built-in encrypted communication and secure commissioning.
- Simple setup: devices are commissioned using a QR code or a manual pairing code.
- Multi-admin support: a single device can be controlled by multiple smart home controllers at the same time.
- IP-based: runs over standard IP networks.

A few concepts worth knowing before you dive into this guide:
- Node: a single Matter device (example: in this guide the ESP32 is a node).
- Endpoint: a functional unit inside a node. A single node (Matter device) can expose multiple endpoints (example: light control and a temperature sensor).
- Cluster: a group of related attributes and commands tied to a function (example: the On/Off cluster has an OnOff attribute and On/Off/Toggle commands).
- Fabric: the logical network created when a controller (Apple Home, Google Home, Alexa, Home Assistant, etc…) commissions your device. A node can belong to multiple fabrics at once.
- Commissioning: the process of assigning a Matter device (node) onto a fabric, using a QR code or an 11-digit manual pairing code. It’s typically done over BLE or Wi-Fi.
- Wi-Fi: Matter runs over IP, and nodes (example: ESP32 devices) can join a Matter network over Wi-Fi.
The ESP32 Arduino Core since version 3.1.0 comes with the Matter library, so you don’t need to install any additional libraries in your Arduino IDE.
Typical Matter Device Workflow
This diagram below illustrates the complete workflow of a Matter device, since it is uncommissioned to normal operation and optional sharing across multiple smart home controller ecosystems.

1. Uncommissioned Device / Node
- First device usage (or after reset)
- Shows QR code + manual pairing code
- User scans QR code or enters manual pairing code into a smart home controller (fabric): Alexa, Apple Home, Google Home, Home Assistant, etc…
2. Commissioning
- Secure pairing session starts (PASE)
- Confirms it’s a Matter device
- Wi-Fi credentials are given (usually over BLE)
- Device joins the Matter fabric (example: Alexa – Echo Dot Max)
3. Joins the Network
- Connects to Wi-Fi
- Becomes reachable via IPv6 + mDNS
4. Normal Operation
- Controllers discover and control the Matter device
- All communication is encrypted
- Works locally even without internet
5. Multi-admin (optional)
- Original QR/pairing code cannot be reused
- Open pairing mode from the first connected app to Generate / Share device by creating a new temporary manual pairing code
- Use the new generated code to add the device to another ecosystem: Apple Home, Google Home, Home Assistant, etc…
- Same Matter device belongs to multiple fabrics and can be controlled by several ecosystems at the same time
Supported ESP32 Chips
The following ESP32 chips support Matter protocol. Additionally, it also shows which ones support CHIPoBLE. For chips that don’t support it, the credentials need to be inserted in the sketch. In the other scenarios, they are transferred over BLE from the controller.
| Chip | Commisioning Path | CHIPoBLE * |
|---|---|---|
| ESP32 | Wi-Fi (enter SSID/Password in sketch) | Off |
| ESP32-S2 | Wi-Fi (enter SSID/Password in sketch) | Off |
| ESP32-S3 | Wi-Fi (fabric/controller) | On |
| ESP32-C3 | Wi-Fi (fabric/controller) | On |
| ESP32-C5 | Wi-Fi (fabric/controller) | On |
| ESP32-C6 | Wi-Fi (fabric/controller) | On |
| ESP32-H2 | Thread (fabric/controller) | On |
* CHIPoBLE stands for CHIP (Connected Home over IP), the original name of the Matter protocol, over BLE (Bluetooth Low Energy).
Arduino Sketch – ESP32 Matter Device: Control On/Off Light
The following example is based on the official Espressif Arduino ESP32 Matter library. It turns your ESP32 into a fully functional Matter device (node) On/Off Light that controls a GPIO pin. The device can be commissioned into any major Matter ecosystem and also controlled locally with a pushbutton.
/*
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-matter-on-off-light/
Copyright 2025 Espressif Systems (Shanghai) PTE LTD. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
*/
#include <Arduino.h>
#include <Matter.h>
#include <Preferences.h>
// Wi-Fi credentials for this sketch. Fill these in when the board cannot commission over BLE (Arduino prebuild on ESP32 / ESP32-S2): the sketch
// joins the AP itself. When Matter commissions over BLE (CHIPoBLE), the hub sends SSID and password — leave the placeholders; they are unused.
#define WIFI_SSID "your-ssid"
#define WIFI_PASSWORD "your-password"
// List of Matter Endpoints for this Node
// On/Off Light Endpoint
MatterOnOffLight OnOffLight;
// it will keep last OnOff state stored, using Preferences
Preferences matterPref;
const char *onOffPrefKey = "OnOff";
// set your board LED pin here
#ifdef LED_BUILTIN
const uint8_t ledPin = LED_BUILTIN;
#else
const uint8_t ledPin = 2; // Set your pin here if your board has not defined LED_BUILTIN
#warning "Do not forget to set the LED pin"
#endif
// set your board USER BUTTON pin here
const uint8_t buttonPin = BOOT_PIN; // Set your pin here. Using BOOT Button.
MatterButton button;
// Matter Protocol Endpoint Callback
bool setLightOnOff(bool state) {
Serial.printf("User Callback :: New Light State = %s\r\n", state ? "ON" : "OFF");
if (state) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
// store last OnOff state for when the Light is restarted / power goes off
matterPref.putBool(onOffPrefKey, state);
// This callback must return the success state to Matter core
return true;
}
void setup() {
// Initialize the USER BUTTON (Boot button) GPIO that will act as a toggle switch
button.begin(buttonPin);
// Initialize the LED (light) GPIO and Matter End Point
pinMode(ledPin, OUTPUT);
Serial.begin(115200);
// CONFIG_ENABLE_CHIPOBLE=n: sketch starts Wi-Fi here; with CHIPoBLE the hub delivers credentials.
#if !CONFIG_ENABLE_CHIPOBLE
matterConnectWiFi(WIFI_SSID, WIFI_PASSWORD);
#endif
// Initialize Matter EndPoint
matterPref.begin("MatterPrefs", false);
bool lastOnOffState = matterPref.getBool(onOffPrefKey, true);
OnOffLight.begin(lastOnOffState);
OnOffLight.onChange(setLightOnOff);
// Matter beginning - Last step, after all EndPoints are initialized
Matter.begin();
matterWaitUntilReady();
Serial.printf("Initial state: %s\r\n", OnOffLight.getOnOff() ? "ON" : "OFF");
OnOffLight.updateAccessory();
}
void loop() {
matterRestartIfNoFabric();
matterButtonEvent_t ev;
while ((ev = button.poll()) != MATTER_BUTTON_NONE) {
if (ev == MATTER_BUTTON_CLICK) {
Serial.println("User button released. Toggling Light!");
OnOffLight.toggle();
} else if (ev == MATTER_BUTTON_LONG_HOLD) {
Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again.");
OnOffLight.setOnOff(false);
Matter.decommission();
}
}
}
You don’t need to install any aditional libraries, depending on your board you might need to insert your network credentials in the following lines in the code. You also need to select in the Tools – Partition Scheme: “Huge APP (3MB No OT /1MB SPIFFS)” and the code will work straight away.
#define WIFI_SSID "REPLACE_WITH_YOUR_SSID";
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD";
How the Code Works
Continue reading to learn how the code works, or skip to the Demonstration section.
Including Libraries
Start by including the following libraries:
#include <Arduino.h>
#include <Matter.h>
#include <Preferences.h>
- Matter.h – Main Matter library (handles the protocol stack)
- Preferences.h – Used to save the last on/off state in non-volatile memory (remembers last state after board reboot)
Learn more about preferences with our guide: ESP32 Save Data Permanently using Preferences Library.
Network Credentials
These Wi-Fi credentials are only needed if the board can’t commission over BLE (Arduino prebuild on ESP32 or ESP32-S2), in that case the sketch joins the network itself. When Matter uses BLE commissioning (CHIPoBLE), the hub provides the SSID and password, so you can leave the default SSID/Password placeholders.
#define WIFI_SSID "REPLACE_WITH_YOUR_SSID";
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD";
Matter Endpoint
The OnOffLight is the Matter endpoint that implements the standard On/Off Light cluster on the ESP32.
MatterOnOffLight OnOffLight;
Preferences
The matterPref and onOffPrefKey store the last light state so it is restored after a reboot.
Preferences matterPref;
const char *onOffPrefKey = "OnOff";
LED Pin
Uses the board’s built-in LED if available, otherwise GPIO 2.
#ifdef LED_BUILTIN
const uint8_t ledPin = LED_BUILTIN;
#else
const uint8_t ledPin = 2;
#warning "Do not forget to set the LED pin"
#endif
BOOT Button
Uses the ESP32 on-board BOOT button (usually GPIO 0) for local GPIO control and factory reset (decommissioning).
const uint8_t buttonPin = BOOT_PIN;
MatterButton button;
setLightOnOff()
The setLightOnOff() callback function turns the physical LED on or off according to the requested Matter state. It also saves the current state to non-volatile storage so it remembers the last state after a board reboot.
bool setLightOnOff(bool state) {
Serial.printf("User Callback :: New Light State = %s\r\n", state ? "ON" : "OFF");
if (state) {
digitalWrite(ledPin, HIGH);
} else {
digitalWrite(ledPin, LOW);
}
matterPref.putBool(onOffPrefKey, state);
return true;
}
setup()
The setup() function starts by intializing the buttonPin and ledPin. It also starts the serial communication.
void setup() {
button.begin(buttonPin);
pinMode(ledPin, OUTPUT);
Serial.begin(115200);
Depending on your board, it connects to Wi-Fi using the network crendetials if CHIPoBLE is disabled.
// CONFIG_ENABLE_CHIPOBLE=n: sketch starts Wi-Fi here; with CHIPoBLE the hub delivers credentials.
#if !CONFIG_ENABLE_CHIPOBLE
matterConnectWiFi(WIFI_SSID, WIFI_PASSWORD);
#endif
This next code snippet initializes the Matter preferences storage and retrieves the last saved state (on/off). It starts the OnOffLight endpoint with that state, and registers the setLightOnOff callback so the physical LED updates when the Matter state changes.
matterPref.begin("MatterPrefs", false);
bool lastOnOffState = matterPref.getBool(onOffPrefKey, true);
OnOffLight.begin(lastOnOffState);
OnOffLight.onChange(setLightOnOff);
The first line begins the Matter stack and waits until it is fully ready. Then, it prints the light’s initial on/off state in the Serial Monitor, and updates the physical accessory (LED) to match that state.
Matter.begin();
matterWaitUntilReady();
Serial.printf("Initial state: %s\r\n", OnOffLight.getOnOff() ? "ON" : "OFF");
OnOffLight.updateAccessory();
loop()
The loop() starts by calling the matterRestartIfNoFabric() function. This is a helper that checks whether the device is still part of a Matter fabric (it’s still commissioned to a controller like Apple Home, Google Home, Alexa, etc…). If the device has no fabric (it’s currently decommissioned), it restarts the Matter stack so it can be discovered and commissioned.
matterRestartIfNoFabric();
Declares a variable ev of type matterButtonEvent_t that represents different button events (short press or long press).
matterButtonEvent_t ev;
The button.poll() is a non-blockingly way to check if the physical BOOT button was pressed.
while ((ev = button.poll()) != MATTER_BUTTON_NONE) {
If you click on-board BOOT with a short press, it toggles the light (if it was On, it turns Off, or if it was already Off, the light is turned On). It also updates the current state to all Matter controllers.
if (ev == MATTER_BUTTON_CLICK) {
Serial.println("User button released. Toggling Light!");
OnOffLight.toggle();
}
Finally, if the on-board BOOT button is pressed for more than 5 seconds, it turns off the light and removes the device from all Matter fabrics (factory reset). The device will need to be commissioned again.
else if (ev == MATTER_BUTTON_LONG_HOLD) {
Serial.println("Decommissioning the Light Matter Accessory. It shall be commissioned again.");
OnOffLight.setOnOff(false);
Matter.decommission();
}
Upload Code to Your Board
After inserting your network credentials, folow these next steps to upload the code to the ESP32 board.
First, select your board: Tools – Board – ESP32 Arduino – select your board (for example ESP32S3 Dev Module).
Then, go to Tools and select the Partition Scheme: “Huge APP (3MB No OT /1MB SPIFFS)”

Important: before the first upload, we recommend erasing all the flash memory. Go to Tools and enable the option Erase All Flash Before Sketch Upload: Enabled. This clears previous Wi-Fi credentials and Matter fabric data. Do this at least for the first upload or when commissioning fails.

Finally, having your board plugged into your computer and with the correct serial port selected, click the Arduino IDE Upload button.

Commissioning Your ESP32 Matter Device
On the first ESP32 boot (or after erasing all the flash memory), open your Arduino IDE Serial Monitor, press the ESP32 on-board RST/EN button

It should print something like this:

You can either use the 11-digit manual pairing code or open the URL in your browser to get a QR code to scan it in your smart home app.

Add Matter Device to Amazon Alexa
For this example, we’ll be using the Amazon Alexa app, but in the next section we’ll show the steps to add to other controller applications.
First, open the Amazon Alexa app and tap the + icon:

Choose the Add Device option:

Select Matter logo or Other.

When asked if the device has a logo, select the “YES” option. Then, scan QR code or enter the manual pairing code:

Having your device fairly close to the matter device, click “Connect“.

The ESP32 is not Matter certified, but add the device by tapping Yes.

Your ESP32 Matter device will be found and connected, click Next.

After successful commissioning the Arduino IDE serial monitor prints “Matter Node is commissioned…” and the LED reflects the current state.

Your light will be added to your Devices list as shown in the next image:

Add Matter Device to Apple Home, Google Home, Home Assistant, or SmartThings
These are the quick instructions on how to add a Matter device to different controller applications. You must have the controller running in your home like Apple Home, Google Home, Home Asssistant or SmartThings.
- Apple Home:
- Open the iPhone Home app
- Tap the + icon on the top right corner
- Add Accessory
- Scan QR code or tap the “More options” link to enter the manual pairing code
- Google Home:
- Open the Google Home app
- Tap the + icon
- Set up device
- New device
- Matter device
- Scan QR code or enter the manual pairing code
- Home Assistant:
- Open Home Assistant
- Go to Settings
- Devices & Services
- Add Integration
- Matter
- Enter the manual pairing code or scan QR code
- Samsung SmartThings:
- Open the SmartThings app
- Tap the + icon
- Select Partner devices: Matter
- Scan QR code or enter the manual pairing code
Important: after commissioning a Matter device to one controller, you cannot reuse the original QR code or manual pairing code to add it to another controller. Instead, you must open a new commissioning window from the first controller’s app (Share / Turn on Pairing Mode / Link to another platform) to generate a temporary new code, then use that code to share the device into the new platform.
Note: some apps may warn that this is not an official or certified device, but you need to select the option to add it.
Demonstration
From a Matter app (like Alexa) or voice hub, you can toggle the light on/off. The GPIO changes according to the command and the state is saved even if your board reboots.

You can also control the ESP32 GPIO using the physical on-board BOOT button. Short press the BOOT button: it toggles on/off (the current state is also updated to all Matter controllers)

IMPORTANT: you can hold the BOOT button for more than 5 seconds to decommission the Matter device (factory reset). The device must be re-commissioned afterwards with a new QR code or by entering the manual pairing code.
Note: if your board reboots, it remembers the last on/off state, because it is restored from NVS (Preferences).
You can watch the video demonstration below:
Troubleshooting
The following table shows the most common errors when following this tutorial, and possible solutions.
| Error | Solution |
| Sketch too large / not enough space / compilation fails | In the Tools menu, you must select the option: Partition Scheme: “Huge APP (3MB No OT /1MB SPIFFS)” |
| Device never shows the pairing code | Check that you’ve entered the correct SSID/password in your code |
| Commissioning fails after previous attempt / Want to re-commission to another controller | – Press the BOOT button 5 seconds – Or you can also go to Tools and enable the option Erase All Flash Before Sketch Upload: Enabled, then re-upload the code to your board |
| No serial output printed | Press the RST/EN button to restart the ESP32 while the Arduino IDE Serial Monitor is open with 115200 baud rate with the correct serial port selected |
Note: in the Arduino IDE Serial monitor, you might see many log messages being printed over time and right after setup. You might see messages like “sending failed”, “transient send error”, “request on unknown cluster”, or similar. They’re usually harmless and you can ignore them unless the device stays unreachable.
Wrapping Up
In this guide, you learned how to turn your ESP32 into a Matter device for a on/off light programmed with Arduino IDE. You’ve also learned the basics about the Matter protocol and how to commission the device to different controllers, such as Alexa, Apple Home, Google Home, Home Assistant, and SmartThings.
If you liked this project, you may also like these other tutorials:
- Building an ESP32 Web Server: The Complete Guide for Beginners
- Getting Started with ESP-NOW (ESP32 with Arduino IDE)
- What is MQTT and How It Works
- ESP32 Save Data Permanently using Preferences Library
Thanks for reading.


Yaaah, diriku lagi cari informasi siapa yang brengsekin saya (Voodoo). Malah cerita yang lain 🗿 diriku mau contra ke person 🎯 gimana coba ? Code-nya wiring diagram yaaa, where’s the came from that black cable, okay brother. Thank you