Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions components/zigbee/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ def require_vfs_select():
CONF_ROUTER,
CONF_SCALE,
BinarySensor,
CONF_TRUST_CENTER_KEY,
CONF_DEVICE_VERSION,
Sensor,
Switch,
)
Expand Down Expand Up @@ -258,6 +260,8 @@ def _require_vfs_select(config):
cv.Optional(CONF_VERSION, default=0): cv.int_,
cv.Optional(CONF_AREA, default=0): cv.int_, # make enum
cv.Optional(CONF_ROUTER, default=False): cv.boolean,
cv.Optional(CONF_TRUST_CENTER_KEY): cv.bind_key,
cv.Optional(CONF_DEVICE_VERSION, default=0): cv.int_,
cv.Optional(CONF_DEBUG, default=False): cv.boolean,
cv.Optional(CONF_COMPONENTS): cv.Any(
cv.one_of("all", "none", lower=True),
Expand Down Expand Up @@ -531,6 +535,10 @@ async def to_code(config):
config[CONF_AREA],
)
)
if CONF_TRUST_CENTER_KEY in config:
cg.add_define("CONF_TRUST_CENTER_KEY", config[CONF_TRUST_CENTER_KEY])
if CONF_DEVICE_VERSION in config:
cg.add_define("CONF_DEVICE_VERSION", config[CONF_DEVICE_VERSION])
for ep in ep_list:
cg.add(
var.create_default_cluster(ep[CONF_NUM], DEVICE_ID[ep[CONF_DEVICE_TYPE]])
Expand Down
2 changes: 2 additions & 0 deletions components/zigbee/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
CONF_ROUTER = "router"
CONF_AS_GENERIC = "as_generic"
CONF_ON_REPORT = "on_report"
CONF_TRUST_CENTER_KEY = "trust_center_key"
CONF_DEVICE_VERSION = "device_version"

# dummies for upstream compatibility
binary_sensor_ns = cg.esphome_ns.namespace("binary_sensor")
Expand Down
47 changes: 46 additions & 1 deletion components/zigbee/zigbee.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ ZigBeeComponent *global_zigbee;

device_params_t coord;

/* On/Off optional attributes (must persist!) */
static uint16_t zb_on_off_on_time = 0;
static bool zb_on_off_global_scene_control = true;

/**
* Creates a ZCL string from the given input string.
*
Expand Down Expand Up @@ -460,7 +464,7 @@ esp_err_t ZigBeeComponent::create_endpoint(uint8_t endpoint_id, esp_zb_ha_standa
esp_zb_endpoint_config_t endpoint_config = {.endpoint = endpoint_id,
.app_profile_id = ESP_ZB_AF_HA_PROFILE_ID,
.app_device_id = device_id,
.app_device_version = 0};
.app_device_version = CONF_DEVICE_VERSION};
return esp_zb_ep_list_add_ep(this->esp_zb_ep_list_, esp_zb_cluster_list, endpoint_config);
}

Expand Down Expand Up @@ -518,6 +522,22 @@ void ZigBeeComponent::setup() {
#endif
esp_zb_init(&zb_nwk_cfg);

#ifdef CONF_TRUST_CENTER_KEY
uint8_t trustkey_[16];
memset(trustkey_, 0, 16);

char temp[3] = {0};
for (int i = 0; i < 16; i++) {
strncpy(temp, &(CONF_TRUST_CENTER_KEY[i * 2]), 2);
trustkey_[i] = std::strtoul(temp, nullptr, 16);
}

ESP_LOGE(TAG, "Zigbee trust center key: %s", format_hex_pretty(trustkey_, 16).c_str());

esp_zb_enable_joining_to_distributed(true);
esp_zb_secur_TC_standard_distributed_key_set(trustkey_);
#endif

esp_err_t ret;

// clusters
Expand All @@ -531,6 +551,31 @@ void ZigBeeComponent::setup() {
}
this->attribute_list_.clear();

// Fix On/Off needed for Philips hue compatibility - some attributes are required by the Hue bridge that aren't in the default cluster, so add them here

for (auto const &[ep_id, dev] : this->endpoint_list_) {

esp_zb_cluster_list_t *cluster_list = std::get<1>(dev);

esp_zb_attribute_list_t *on_off_cluster =
esp_zb_cluster_list_get_cluster(cluster_list,
ESP_ZB_ZCL_CLUSTER_ID_ON_OFF,
ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);

if (on_off_cluster != nullptr) {

ESP_LOGD(TAG, "Patching On/Off cluster for endpoint %d", ep_id);

esp_zb_on_off_cluster_add_attr(on_off_cluster,
ESP_ZB_ZCL_ATTR_ON_OFF_ON_TIME,
&zb_on_off_on_time);

esp_zb_on_off_cluster_add_attr(on_off_cluster,
ESP_ZB_ZCL_ATTR_ON_OFF_GLOBAL_SCENE_CONTROL,
&zb_on_off_global_scene_control);
}
}

// endpoints
for (auto const &[ep_id, dev] : this->endpoint_list_) {
// create_default_cluster(key, val);
Expand Down
37 changes: 37 additions & 0 deletions example_onboard_led_hue.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
esphome:
name: hue_light1
friendly_name: hue_light1
min_version: 2026.2.0

external_components:
- source:
type: git
url: https://github.com/mbchristoff/zigbee_esphome
components: [zigbee]

esp32:
variant: ESP32H2 # Either put ESP32C6 or ESP32H2 depending on the board that you have
partitions: partitions_zb.csv
framework:
type: esp-idf

# Enable logging
logger:

zigbee:
id: "zb"
trust_center_key: "81xxxxxxxxxxxxxxxxxxxxxxxxxxxxB8"
device_version: 1
components: all
on_join:
then:
- logger.log: "Joined network"

light:
- platform: esp32_rmt_led_strip
rgb_order: GRB
pin: 8
num_leds: 1
id: light_1
name: "led"
chipset: ws2812