Library / SDK
luar123/zigbee_esphome avatar
luar123/zigbee_esphome

zigbee_esphome, turning ESPHome into a Zigbee end device

External zigbee component

583 stars69 forksPythonLicense varies

At a glance

What is it?
zigbee_esphome is an ESPHome external component that puts an ESP32 with an 802.15.4 radio on a Zigbee network as an end device, with automatic endpoint generation for sensors, switches and lights, or hand-written cluster definitions. It is a single-contributor project with no coordinator support, and the master branch moved to a different Zigbee stack.
Who is it for?
zigbee_esphome suits a maker who already runs ESPHome, wants a battery-powered sensor on a Zigbee network, and is prepared to hand-write cluster definitions when the automatic ones are not enough. It does not suit a household that needs a coordinator, and it does not suit a team that needs a stable configuration schema, because the project states plainly that config validation is not complete.
Can I use it commercially?
Not without permission. GitHub finds no licence file in the repository, and without a licence all rights are reserved by default: you may read the code but not reuse it. Check the README, or ask the authors, before using it.
Is it still maintained?
Yes. The repository last received commits 6 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

An ESP32 that joins someone else's Zigbee network

zigbee_esphome is an external Zigbee component for ESPHome, which means it is a piece of ESPHome firmware configuration rather than a standalone program. The device it produces joins an existing Zigbee network as an end device and reports what it has to a coordinator.

The audience is narrow and specific: someone with a Zigbee installation, a sensor or switch they want to expose to it, and an ESP32 with an 802.15.4 radio. The project states it is tested on the ESP32-H2 and the ESP32-C6, and that in theory it is also compatible with all ESP32 models with an 802.15.4 radio, naming the H2, C5, C6, H4, H21 and S31, but only once those are supported by ESPHome and by the Espressif ESP Zigbee SDK 2.0.

That last clause does a lot of work. The component is bound to a Zigbee stack, and the stack version matters.

The master branch is based on Espressif's self-developed proprietary Zigbee stack, the one used by ESP Zigbee SDK 2.0, while the v1.x branch was based on the ZBOSS stack used by SDK 1.x. The README carries a prominent warning that this is a zigbee-sdk v2.0 implementation and that it is a breaking change that needs a re-join, with a link to the issues and limitations discussion at number 96, and it points anyone who wants to stay on v1.x at the v1.x branch.

The licence is not stated in the repository metadata, and the packaging file in the repository describes a package named esphome licensed MIT, which is the upstream ESPHome project rather than this component. The last push to the repository was on 2026-10-17, and there are no tagged releases.

Basic mode generates the endpoints for you

There are two ways to describe your device, and the automatic one is the entry point.

In basic mode, adding `components: all` generates the endpoint definition automatically. The supported ESPHome components are sensor, binary_sensor, light and switch, and the mapping to Zigbee clusters is direct.

| ESPHome Entity | Zigbee Cluster | | --------------- | ------------------------------------------------------------------ | | `light` | `light` | | `switch` | `on_off`, `binary_output` | | `binary_sensor` | `binary_input` | | `sensor` | `analog_input` or mapped to specific clusters such as `temperature` |

For sensors, the unit and type are set automatically. The mapping from an ESPHome entity to a specific cluster, rather than to the generic analog input, is what makes a temperature sensor appear as a temperature sensor to the coordinator instead of a raw analog reading.

The example configuration is as short as it gets.

yaml
zigbee:
  id: "zb"
  components: all

Two caveats are stated in the same section, and both matter. Because this is an external component, the whole implementation is described as a bit hacky and likely to fail with some setups, and it is not possible to tweak the generated definitions. And the definitions are not complete, with an invitation to open an issue or pull request against the file that does the generation, `zigbee_ep.py`.

Each entity creates a new endpoint, and the endpoint count is a hard limit downstream, which is where one of the more serious constraints in the limitations list comes from.

Basic mode also requires the platformio toolchain, so a build of this component is not a pure-Python operation even though the configuration is YAML.

The limitations list is the most useful section in the README

The project publishes its limitations prominently, and they deserve to be read before any configuration is written, because several of them change what you can build.

The endpoint limit is the sharpest. Officially the Zigbee stack supports only 10 endpoints. This is not enforced, and at least for sensor endpoints more than 10 seem to work, but more than 10 light endpoints will crash.

The rest of the list covers what is not there. There are no coordinator devices. Scenes are not implemented. The attribute set action works only with numeric types and character strings, and the attribute OnValue trigger works only with numeric types. Reporting can be enabled but not configured, which means you can ask a sensor to report and you cannot set how often. Control devices such as switches are not supported, with a link to a workaround discussion.

Two items are ZHA-specific and worth understanding because ZHA is a common coordinator implementation. The analog input cluster used for sensors without a unit or type is ignored, which is the generic fallback path failing in a specific and diagnosable way. And the minimum reporting interval is set to high values, 30 seconds, for some sensors and cannot be changed, with the advice to keep that in mind if reporting seems not to work properly.

There is also a list of what is not planned, with an invitation to submit pull requests anyway. Zigbee OTA upgrade cluster support, which would allow over-the-air firmware updates over Zigbee, is explicitly not planned. Coordinator devices are not planned. Binding configuration in YAML and reporting configuration in YAML are not planned. Control device support such as switches is not planned.

The OTA exclusion is the one to dwell on, because it is a common expectation for a battery device on a mesh network. A device that cannot be updated over the air has to be physically reflashed.

What the component actually does on the network

The feature list describes the on-device behaviour, and it is where the implementation detail shows.

There is automated generation of the Zigbee definition for lights, switches, sensors and binary sensors, and a definition of the endpoints, clusters and attributes supported by the ESP Zigbee SDK 2.0. On top of that there is a set of actions and triggers: a set attributes action, a manual report action, a reset Zigbee action, a join trigger, an attribute received trigger, and time sync with the coordinator.

The join trigger and the time sync are the two that matter operationally. Joining is what puts the device on the network in the first place, and time sync with the coordinator means the device's clock is corrected against the network rather than drifting from a battery-backed RTC. On a node that wakes every few minutes to report a temperature, a drifting clock is a real problem for anything that timestamps data.

The action and trigger split is the interesting part of the design. The set attributes action writes to a cluster attribute, the manual report action asks a device to report now rather than waiting for its interval, the reset Zigbee action restarts the stack, and the attribute received trigger fires when the coordinator or another device writes to one of your attributes. Together they let an ESPHome automation act on the mesh rather than only report to it.

There is also a way to avoid lambdas. The feature list says that normal, binary and text sensors, switches and lights can be connected to attributes without the need for lambdas or actions, which is the point of a declarative configuration. The advanced mode is where you write the endpoint and cluster definitions yourself for devices whose cluster layout the basic mode cannot infer.

Two hardware notes. Wifi co-existence is supported on the ESP32-C6 and the ESP32-C5, which matters because a 2.4 GHz radio next to a wifi radio on the same chip is a known source of trouble. And deep sleep should work, which is what makes a battery-powered node viable.

Putting it in an ESPHome configuration

The usage section is short, and the integration mechanism is the standard ESPHome external component syntax.

yaml
external_components:
  - source: github://luar123/zigbee_esphome
    components: [zigbee]

zigbee:
  components: all # to add all supported components
  ...

The `source` line points at the GitHub repository and the `components` list names the single component to pull in, which is `zigbee`. The `zigbee:` block is where the device is configured, and the `components: all` line is what switches on the automatic generation described earlier.

The configuration variables list is where the identity of the device is set, and every one of them maps to a field in the basic cluster, which is what a coordinator reads to identify the device.

The `name` sets the Zigbee Model Identifier and defaults to `esphome.name`, the `manufacturer` sets the Zigbee Manufacturer Name and defaults to the literal string `esphome`, the `date` is the Date Code and defaults to the build time, `power_supply` is the Zigbee Power Source with zero meaning unknown and the enumerated values being single phase mains, three phase mains and battery, and `version` is the Zigbee App Version defaulting to zero. There is also `area` for the Zigbee Physical Environment, `router` to create a router device instead of an end device, and `device_version` for the Home Automation Profile device version, with the note that custom values might be needed for compatibility with some vendors.

Two options are worth calling out. `as_generic` uses generic or basic clusters where possible, currently for sensors and switches, and defaults to false. And `components` accepts `all`, None for no definitions, or a list of component ids, and a list can be combined with manual definitions in the endpoints section.

The repository carries the example configurations at the top level, so `example_esp32h2.yaml`, `example_esp32c6.yaml`, `example_esp32h2_basic.yaml` and `example_time.yml` are the fastest way to see a working configuration, and `example_aht10_esp32h2.yaml` shows a real sensor attached.

The state of the project and where to get help

Two things in the README tell you what kind of project this is and how to treat its configuration.

The first is the warning that config validation is not complete, with the instruction to always consult the Zigbee Cluster Library for cluster definitions, and a link to that document. The Zigbee Cluster Library is the specification of what each cluster and attribute means, published by the Connectivity Standards Alliance, and it is linked here as a PDF of the 5123 document, the ZCL specification.

That instruction is a genuine dependency on external documentation, and it is the honest signal about the state of the project. The component generates definitions, it does not validate them against the full cluster specification, and a configuration that passes the build can still have a cluster or attribute that does not match what your coordinator expects.

The second is the request to help collect working cluster definitions in a discussions thread, number 22, alongside the note to check the troubleshooting section first. The project is asking users to contribute the knowledge it does not have, which is a reasonable thing for a project without a coordinator implementation to do, and it also means the documentation you will find is community-contributed rather than authoritative.

The ToDo list is short and stated as short to mid term: light effects through identify cluster commands, and more components to support basic mode. The not-planned list is longer, as described earlier.

For a first real use, the path is straightforward. Take one of the example configurations, build it for the ESP32-H2 or C6, join the device to a network with the join trigger, and confirm that the attributes appear on the coordinator. Then read the limitations list again with the specific sensor in mind, because the ZHA reporting interval behaviour and the analog input ignore rule are the two that most often make a working device look broken.

Editorial conclusion

zigbee_esphome suits a maker who already runs ESPHome, wants a battery-powered sensor on a Zigbee network, and is prepared to hand-write cluster definitions when the automatic ones are not enough. It does not suit a household that needs a coordinator, and it does not suit a team that needs a stable configuration schema, because the project states plainly that config validation is not complete. Verify first that your coordinator accepts the device, since the master branch implements Zigbee SDK 2.0 and a device must re-join after the switch from the 1.x branch, and check the cluster library against the Zigbee Cluster Library for the attributes you intend to use.

Frequently asked questions

What is zigbee_esphome and what hardware does it need?

It is an ESPHome external component that lets an ESP32 with an 802.15.4 radio join a Zigbee network as an end device. It is tested on the ESP32-H2 and ESP32-C6, and in theory works on other ESP32 models with an 802.15.4 radio once ESPHome and the ESP Zigbee SDK 2.0 support them.

How do I add the zigbee component to an ESPHome configuration?

Add it under external_components with the source set to github://luar123/zigbee_esphome and components set to the zigbee component, then configure the zigbee block. Setting components to all generates the endpoint definitions automatically for sensor, binary_sensor, light and switch entities.

What are the main limitations of zigbee_esphome?

There is no coordinator support and scenes are not implemented. The attribute set action and the OnValue trigger work only with numeric types and character strings, reporting can be enabled but not configured, and control devices such as switches are not supported. Officially the Zigbee stack supports only 10 endpoints, and more than 10 light endpoints will crash.

Does zigbee_esphome work with the v1.x Zigbee stack?

Not on the master branch, which is based on Espressif's proprietary stack from ESP Zigbee SDK 2.0 and is a breaking change requiring devices to re-join. If you want to stay on the ZBOSS-based stack from SDK 1.x, the project points you at the v1.x branch.

Can zigbee_esphome update device firmware over the air?

No. Zigbee OTA upgrade cluster support, which would allow over-the-air firmware updates over Zigbee, is on the not planned list, so a device has to be physically reflashed.

Official sources

  1. Issues
  2. luar123/zigbee_esphome on GitHub
  3. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/luar123-zigbee-esphome.svg)](https://hysenlabs.com/projects/luar123-zigbee-esphome)

Was this useful?