Software
ESP32 Matter: 69 Open-Source Smart-Home Devices, No Cloud Required
A from-scratch toolkit for building Matter smart-home devices on the ESP32: 69 real, buildable device types, a wizard that writes the build commands for you, and nothing that phones home.
If you've followed the HomeKit development guide or the Wi-Fi Bootstrap project on this site, esp32-matter is the next step: instead of one accessory, it's a complete, self-contained toolkit for turning an ESP32 into any of 69 different Matter smart-home devices, lights, sensors, switches, locks, thermostats, appliances and more, without depending on a single line of code you can't read yourself.
This project is still under active development
Most of the 69 device types build cleanly in Docker but haven't been tested on real hardware yet (the project is honest about exactly which ones have, see the verification table below). Automatic over-the-air updates aren't wired up yet, either. Treat it as a serious, working toolkit that keeps growing, not a finished, boxed product.
New to this? Start here: what is Matter?
Matter is a shared smart-home standard backed by Apple, Google, Amazon, Samsung and dozens of other manufacturers. The idea is simple: one certified Matter device should work with Apple Home, Google Home, Amazon Alexa and Samsung SmartThings, without needing a separate app or hub for each ecosystem.
Two details matter (no pun intended) for anyone building their own hardware:
- Pairing happens over Bluetooth LE, then the device joins your Wi-Fi or Thread network for normal use.
- Control happens over your local network, not through a manufacturer's cloud. Paired with a local hub like Home Assistant, a Matter device can run 100% locally: nothing about turning your lamp on or off has to leave your house.
That local-first design is exactly why esp32-matter exists: it lets you build your own Matter devices, on hardware you already know (the ESP32), without adopting anyone's cloud service to do it.
What esp32-matter actually gives you
It's a collection of 69 separate, self-contained firmware projects, one per device type, built on Espressif's own open-source esp-matter SDK, plus a wizard that saves you from hand-editing any of them. Five principles the project holds itself to, from its own README:
- No hidden code. Everything is plain, readable C++, shell and YAML on top of the open-source SDK, no prebuilt or obfuscated blobs.
- No cloud, no data sharing, no telemetry. Pairing over Bluetooth LE and Wi-Fi/Thread, control over your local network. Nothing phones home.
- Local QR generation. The commissioning QR code every Matter device needs is generated entirely offline, on your own machine.
- Reproducible builds. The whole toolchain is pinned to one specific Docker image tag, so a build today matches a build next year.
- MIT-licensed. Free to use, modify and ship.
What you need
Hardware
- An ESP32 board. The classic ESP32 DevKit (WROOM-32) is the default target and matches every wiring example. The ESP32-C6 and several other Espressif chips (C2, C3, C5, C61, S3, H2) are also supported.
- A USB cable (plus a USB-to-serial adapter if the board has no on-board USB).
- Whatever the device itself needs, an LED, a relay module, a sensor. Each firmware's
main/app_main.cppdocuments its exact wiring in its own header comment.
Software, on your computer only
- Docker Desktop, installed and running. All compiling happens inside a container, there's no local ESP-IDF toolchain to install or break.
- Python 3 and
esptool, for flashing over USB:
python3 -m pip install esptool
esptool.py --version- A Matter controller to commission the finished device: Home Assistant is the recommended choice (see the commissioning note below), or Apple Home, Google Home, Amazon Alexa, or SmartThings.
One-time setup, run once on your computer:
git clone https://github.com/AchimPieters/esp32-matter.git
cd esp32-matter
docker pull espressif/esp-matter:release-v1.6_idf_v5.5.4No --recursive needed: the esp-matter SDK and connectedhomeip live inside the Docker image itself, not as git submodules in this repository.
The easy way: the Product Wizard
For a first build, or if you'd rather not memorize any of the commands above, the repository ships a local, offline, no-build web page: tools/product-wizard/index.html. Nothing is uploaded anywhere, it stores your product list only in your own browser's local storage. Open it (open tools/product-wizard/index.html, or just drag the file into a browser tab), then walk through four steps: pick one of the device types, pick your ESP32 chip, set the GPIO pins and any optional features, then review the summary. The last step, Generate Firmware, hands you two ready-to-run commands: one that builds the firmware and generates its QR code inside Docker, and one that flashes it over USB with esptool. Copy, paste, done.
The advanced way: building firmware/light by hand
For a technical reader who wants to understand every step, the README walks through building firmware/light/, a minimal On/Off light with an LED on GPIO 2 of a classic ESP32, the reference every other device type is copied from.
1. Open the pinned dev environment
./tools/dev.shThis wraps a single Docker command that mounts the repository and boots into a container with ESP-IDF and esp-matter already activated. One documented gotcha: the container's entrypoint drops you into esp-matter's own path, not /project, regardless of the -w flag, your repo is still mounted at /project, so use the absolute path.
2. Build, inside the container
cd /project/firmware/light
idf.py set-target esp32
idf.py build3. Generate the commissioning QR code, offline, inside the container
pip install esp-matter-mfg-tool
cd /project/firmware/light
/project/tools/gen_factory.shRe-run gen_factory.sh once per physical unit, every device needs its own commissioning identity.
4. Flash, from your host, outside the container
Docker Desktop on macOS and Windows can't see the USB serial port, so this last step runs on your host machine directly, using the offsets the build itself just printed:
esptool.py --chip esp32 -p <PORT> -b 460800 --before default_reset --after hard_reset write_flash \
--flash_mode dio --flash_size 4MB --flash_freq 40m \
0x1000 firmware/light/build/bootloader/bootloader.bin \
0x8000 firmware/light/build/partition_table/partition-table.bin \
0x10000 firmware/light/build/ota_data_initial.bin \
0x20000 firmware/light/build/matter_light.bin \
0x3E0000 firmware/light/out/*/*/*-partition.binTwo things worth knowing if a board won't boot: the bootloader offset is 0x1000 on the classic ESP32 but 0x0 on every later chip, and ota_data_initial.bin at 0x10000 is required because this partition table has no separate factory app slot, only OTA A/B slots, so the bootloader needs it to know which slot to boot.
5. Commission
Open your controller app, choose Add device, and scan the QR code from step 3. Toggle it and watch the LED, and the serial log, respond.
A real caveat: Apple Home and Google Home certification
This is the honest part worth reading before you start. gen_factory.sh generates a self-signed test Product Attestation Authority the first time it runs. Home Assistant and the chip-tool CLI accept that without complaint, so day-to-day home and hobby use with Home Assistant works today, fully locally. Apple Home and Google Home, in their normal consumer pairing flow, validate the device-attestation chain against their own bundled list of industry-recognised roots, and a locally generated test certificate will never be on that list. Getting a device onto Apple Home or Google Home that way needs a real Vendor ID from the Connectivity Standards Alliance and a matching attestation chain, which is a certification process this project can't shortcut for you.
The device catalog: 69 types, and an honest verification status
Every folder under firmware/ is real, buildable firmware, not a placeholder, spanning lighting, switches and remotes, outlets and power monitoring, sensors, climate and ventilation, doors and closures, appliances, doorbells, and bridges (Zigbee, BLE Mesh, Thread and a two-chip Matter camera). Each device's main/app_main.cpp opens with a header comment documenting exactly what was checked against the Matter specification and the chip's own datasheet.
The project marks every device type with one of two states, and doesn't blur the line between them:
| Marker | Meaning |
|---|---|
| Verified | Built, flashed, commissioned and exercised on real hardware. |
| Build-verified | Compiles cleanly for its target chip inside Docker; the runtime wiring is written carefully against the SDK source and datasheets, but the hardware for that specific device type simply wasn't on hand to test. |
As of this writing, hardware has actually confirmed: the On/Off Light, Contact Sensor, single-button Switch, Outlet, Temperature Sensor (SHT3x/DHT11/DHT22), Light Sensor (boot only), Dimmable Light, Addressable LED Strip (WS2812B, SK6812 RGBW), and Occupancy Sensor. Every other device type, the remaining majority of the catalog, is build-verified only for now. That single fact is probably the clearest evidence of how the project describes its own "in development" status: not a vague disclaimer, but a specific, per-device list.
For advanced users: repository layout and adding a device type
Each of the 69 folders under firmware/<type>/ follows the exact same shape: a documented main/app_main.cpp, a root CMakeLists.txt, a partitions.csv with OTA A/B slots and a separate factory-data partition, and an sdkconfig.defaults wiring in the factory-data provider and the OTA requestor cluster. Compile-time options live as #defines near the top of app_main.cpp (sensor chip choice, GPIO pins, button counts), which is exactly what the wizard edits with sed on your behalf, or you can edit them by hand.
Adding a brand-new device type follows a documented pattern: copy the closest existing folder, swap the endpoint helper esp-matter ships for that device type (preferring a complete top-level helper where one exists, since it wires up the mandatory Descriptor cluster for you, a cluster Apple Home rejects a device for lacking but Home Assistant silently tolerates), rename the CMake project, and verify the result against the CSA's own device-type XML rather than trusting a secondary summary. A few build-system gotchas are already worked around in every CMakeLists.txt here, worth knowing before you copy one: don't add esp-matter's own examples/common to EXTRA_COMPONENT_DIRS unless you actually use something from it, and a couple of compiler flags (like -DCHIP_HAVE_CONFIG_H) have to be set project-wide before the project() call, setting them only on the main component isn't enough.
Supported targets: the classic ESP32 (WROOM-32) by default, plus ESP32-C2, C3, C5, C6, C61, S3 and H2 via idf.py set-target. The C5, C6 and H2 chips are the 802.15.4/Thread-capable ones; this project builds Matter-over-Thread firmware for them, never Zigbee firmware. ESP32-H4/H21 (their radio support isn't enabled in this ESP-IDF version yet), P4 (no radio of its own) and S2 (no Bluetooth LE, so no standard Matter commissioning) are excluded for hardware reasons, not oversights.
Security hardening, when you're ready to ship something
The commented-out CONFIG_SECURE_* options in every sdkconfig.defaults point at flash encryption and Secure Boot v2, and the project supports signed OTA updates once you turn that on. The dedicated nvs_keys partition is already declared encrypted in every partitions.csv. The README's own advice is worth repeating: leave these off while you're learning, since they make re-flashing harder, then turn them on before you ship anything for real. Full details live in the repository's own SECURITY.md.
What isn't finished yet
In the project's own words, this is a genuine firmware project, not a no-code app: you work from the command line with ESP-IDF and C++, inside Docker so there's no local toolchain to break. Beyond that trade-off, two concrete gaps are worth knowing about before you rely on this for anything important:
- OTA updates aren't fully wired up. 67 of the 69 firmware types already build with Matter's OTA Requestor cluster enabled and the partitions it needs, and it's been verified on real hardware for the Contact Sensor and Switch. But an actual over-the-air transfer needs a separate OTA Provider node commissioned onto the same network actually serving a firmware file, that piece doesn't exist yet. For now, updating a device means rebuilding and re-flashing it by hand.
- There's no automated CI. An automated build pipeline was tried, but the multi-gigabyte Docker image stalled GitHub's own hosted runners, so it was reverted rather than left flaky. Releases are manual: build and flash straight from this README.
None of that makes the toolkit unusable today, Home Assistant users get a fully local, fully working setup right now, it just means treating this as an actively evolving project rather than a finished 1.0.
Where to go from here
The full repository, including the complete 69-device catalog table, the per-device engineering notes in its own CLAUDE.md, and the wizard's source, is open on GitHub: github.com/AchimPieters/esp32-matter. If you're setting up the ESP-IDF and Docker side of things for the first time, the ESP32 HomeKit development guide on this site covers the same Docker-based toolchain in more depth. Issues and pull requests are welcome, new device types are expected to follow the existing pattern: a self-contained firmware folder, a documented header comment, verification against the CSA device-type specification, and an honest note about what has and hasn't been tested on real hardware.