Closed script0803 closed 1 week ago
Partial code:
static void bind_cb(esp_zb_zdp_status_t zdo_status, void *user_ctx)
{
ESP_LOGI(TAG, "%d",zdo_status);
if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) {
ESP_LOGI(TAG, "Bind response from address(0x%x), endpoint(%d) with status(%d)", ((zdo_info_user_ctx_t *)user_ctx)->short_addr,
((zdo_info_user_ctx_t *)user_ctx)->endpoint, zdo_status);
/* configure report attribute command */
esp_zb_zcl_config_report_cmd_t report_cmd;
bool report_change = 0;
report_cmd.zcl_basic_cmd.dst_addr_u.addr_short = on_off_light.short_addr;
report_cmd.zcl_basic_cmd.dst_endpoint = on_off_light.endpoint;
report_cmd.zcl_basic_cmd.src_endpoint = HA_ONOFF_SWITCH_ENDPOINT;
report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
report_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF;
esp_zb_zcl_config_report_record_t records[] = {
{ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV, ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID, ESP_ZB_ZCL_ATTR_TYPE_BOOL, 0, 30, &report_change}};
report_cmd.record_number = sizeof(records) / sizeof(esp_zb_zcl_config_report_record_t);
report_cmd.record_field = records;
/* ec report init */
esp_zb_zcl_config_report_cmd_t report_ec_cmd;
int16_t report_change_ec = 0;
report_ec_cmd.zcl_basic_cmd.dst_addr_u.addr_short = on_off_light.short_addr;
report_ec_cmd.zcl_basic_cmd.dst_endpoint = on_off_light.endpoint;
report_ec_cmd.zcl_basic_cmd.src_endpoint = HA_ONOFF_SWITCH_ENDPOINT;
report_ec_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
report_ec_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT;
esp_zb_zcl_config_report_record_t ec_records[] = {
{
.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV,
.attributeID = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID,
.attrType = ESP_ZB_ZCL_ATTR_TYPE_U16,
.min_interval = 0,
.max_interval = 5,
.reportable_change = &report_change_ec,
},
{
.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV,
.attributeID = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID,
.attrType = ESP_ZB_ZCL_ATTR_TYPE_U16,
.min_interval = 0,
.max_interval = 5,
.reportable_change = &report_change_ec,
},
{
.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV,
.attributeID = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_ID,
.attrType = ESP_ZB_ZCL_ATTR_TYPE_S16,
.min_interval = 0,
.max_interval = 5,
.reportable_change = &report_change_ec,
}};
report_ec_cmd.record_number = sizeof(ec_records) / sizeof(esp_zb_zcl_config_report_record_t);
report_ec_cmd.record_field = ec_records;
/* meter report init */
esp_zb_zcl_config_report_cmd_t report_meter_cmd;
int16_t report_change_meter = 1;
report_ec_cmd.zcl_basic_cmd.dst_addr_u.addr_short = on_off_light.short_addr;
report_ec_cmd.zcl_basic_cmd.dst_endpoint = on_off_light.endpoint;
report_ec_cmd.zcl_basic_cmd.src_endpoint = HA_ONOFF_SWITCH_ENDPOINT;
report_ec_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
report_ec_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_METERING;
esp_zb_zcl_config_report_record_t meter_records[] = {
{
.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV,
.attributeID = ESP_ZB_ZCL_ATTR_METERING_CURRENT_SUMMATION_DELIVERED_ID,
.attrType = ESP_ZB_ZCL_ATTR_TYPE_U48,
.min_interval = 0,
.max_interval = 25,
.reportable_change = &report_change_meter,
},
{
.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV,
.attributeID = ESP_ZB_ZCL_ATTR_METERING_CURRENT_SUMMATION_RECEIVED_ID,
.attrType = ESP_ZB_ZCL_ATTR_TYPE_U16,
.min_interval = 0,
.max_interval = 25,
.reportable_change = &report_change_meter,
}};
report_ec_cmd.record_number = sizeof(meter_records) / sizeof(esp_zb_zcl_config_report_record_t);
report_ec_cmd.record_field = meter_records;
esp_zb_zcl_config_report_cmd_req(&report_cmd);
esp_zb_zcl_config_report_cmd_req(&report_ec_cmd);
esp_zb_zcl_config_report_cmd_req(&report_meter_cmd);
}
}
static void ieee_cb(esp_zb_zdp_status_t zdo_status, esp_zb_ieee_addr_t ieee_addr, void *user_ctx)
{
if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) {
memcpy(&(on_off_light.ieee_addr), ieee_addr, sizeof(esp_zb_ieee_addr_t));
ESP_LOGI(TAG, "IEEE address: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
ieee_addr[7], ieee_addr[6], ieee_addr[5], ieee_addr[4],
ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0]);
/* bind the on-off light to on-off switch */
esp_zb_zdo_bind_req_param_t bind_req;
memcpy(&(bind_req.src_address), on_off_light.ieee_addr, sizeof(esp_zb_ieee_addr_t));
bind_req.src_endp = on_off_light.endpoint;
bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF;
bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED;
esp_zb_get_long_address(bind_req.dst_address_u.addr_long);
bind_req.dst_endp = HA_ONOFF_SWITCH_ENDPOINT;
bind_req.req_dst_addr = on_off_light.short_addr;
static zdo_info_user_ctx_t test_info_ctx;
test_info_ctx.endpoint = HA_ONOFF_SWITCH_ENDPOINT;
test_info_ctx.short_addr = on_off_light.short_addr;
esp_zb_zdo_device_bind_req(&bind_req, bind_cb, (void *) & (test_info_ctx));
}
}
static void ep_cb(esp_zb_zdp_status_t zdo_status, uint8_t ep_count, uint8_t *ep_id_list, void *user_ctx)
{
if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) {
ESP_LOGI(TAG, "Active endpoint response: status(%d) and endpoint count(%d)", zdo_status, ep_count);
for (int i = 0; i < ep_count; i++) {
ESP_LOGI(TAG, "Endpoint ID List: %d", ep_id_list[i]);
}
}
}
static void simple_desc_cb(esp_zb_zdp_status_t zdo_status, esp_zb_af_simple_desc_1_1_t *simple_desc, void *user_ctx)
{
ESP_LOGI(TAG, "111%d",zdo_status);
if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) {
ESP_LOGI(TAG, "Simple desc response: status(%d), device_id(%d), app_version(%d), profile_id(0x%x), endpoint_ID(%d)", zdo_status,
simple_desc->app_device_id, simple_desc->app_device_version, simple_desc->app_profile_id, simple_desc->endpoint);
for (int i = 0; i < (simple_desc->app_input_cluster_count + simple_desc->app_output_cluster_count); i++) {
ESP_LOGI(TAG, "Cluster ID list: 0x%x", *(simple_desc->app_cluster_list + i));
}
}
}
static void user_find_cb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx)
{
if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) {
ESP_LOGI(TAG, "Match desc response: status(%d), address(0x%x), endpoint(%d)", zdo_status, addr, endpoint);
/* save into remote device record structure for future use */
on_off_light.endpoint = endpoint;
on_off_light.short_addr = addr;
/* find the active endpoint */
esp_zb_zdo_active_ep_req_param_t active_ep_req;
active_ep_req.addr_of_interest = on_off_light.short_addr;
esp_zb_zdo_active_ep_req(&active_ep_req, ep_cb, NULL);
/* get the node simple descriptor */
esp_zb_zdo_simple_desc_req_param_t simple_desc_req;
simple_desc_req.addr_of_interest = addr;
simple_desc_req.endpoint = endpoint;
esp_zb_zdo_simple_desc_req(&simple_desc_req, simple_desc_cb, NULL);
/* get the light ieee address */
esp_zb_zdo_ieee_addr_req_param_t ieee_req;
ieee_req.addr_of_interest = on_off_light.short_addr;
ieee_req.dst_nwk_addr = on_off_light.short_addr;
ieee_req.request_type = 0;
ieee_req.start_index = 0;
esp_zb_zdo_ieee_addr_req(&ieee_req, ieee_cb, NULL);
esp_zb_zcl_read_attr_cmd_t read_req;
uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID};
read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
read_req.attr_number = sizeof(attributes) / sizeof(uint16_t);
read_req.attr_field = attributes;
read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ON_OFF;
read_req.zcl_basic_cmd.dst_endpoint = on_off_light.endpoint;
read_req.zcl_basic_cmd.src_endpoint = HA_ONOFF_SWITCH_ENDPOINT;
read_req.zcl_basic_cmd.dst_addr_u.addr_short = on_off_light.short_addr;
esp_zb_zcl_read_attr_cmd_req(&read_req);
}
}
@script0803 ,
I think if you use the original code, it can work as expected.
I encountered two incorrect ZDO statuses, 'ESP_ZB_ZDP_STATUS_INSUFFICIENT_SPACE' and 'ESP_ZB_ZDP_STATUS_BINDING_TABLE_FULL'.
Could you please provide more details on where the two incorrect statuses are being triggered? More specific context will help in identifying and resolving the issue effectively.
@xieqinan ,
I tried using the original code and got the same error.
'ESP_ZB_ZDP_STATUS_INSUFFICIENT_SPACE' is triggered in simple_desc_cb().
'ESP_ZB_ZDP_STATUS_BINDING_TABLE_FULL' is triggered in bind_cb().
Hi @script0803,
The bind table size is 32 by default. I'm not sure what operations on your side caused it to fill up. Could you please provide a .pcap
file to help us address this issue?
Hi @xieqinan , Of course, but GitHub does not seem to support uploading pcap type files
@script0803 ,
You can use the zip
compress .pcap file first, then upload it.
@xieqinan Thanks for your help! log.zip
Hi @script0803 ,
The .pcap
file shows that the Insufficient Space
status originates from the coordinator’s response. However, the coordinator is not an ESPRESSIF device. Could you please double-check the number of clusters on the coordinator's endpoint 1?
The bind request as the same.
Hi @xieqinan ,
I use Zigbee2MQTT for debugging and use Sonoff Dongle-E as coordinator. You can see that I only connect the ESP32H2 development board.
I noticed that the error was insufficient bind table space, but I tried to adjust the bind table, and the results still showed these two errors.
ESP_ERROR_CHECK(esp_zb_aps_src_binding_table_size_set(64)); ESP_ERROR_CHECK(esp_zb_aps_dst_binding_table_size_set(64))
The following is the cluster I use。
The following is my log after startup and network access. 138 and 140 are the two errors we just pointed out. I debugged them and asked them to output the errors.
I (23) boot: ESP-IDF v5.4-dev-3489-g6e5a178b31 2nd stage bootloader I (23) boot: compile time Oct 25 2024 10:50:08 I (25) boot: chip revision: v0.1 I (27) boot: efuse block revision: v0.3 I (32) boot.esp32h2: SPI Speed : 64MHz I (37) boot.esp32h2: SPI Mode : DIO I (41) boot.esp32h2: SPI Flash Size : 2MB I (46) boot: Enabling RNG early entropy source... I (52) boot: Partition Table: I (55) boot: ## Label Usage Type ST Offset Length I (62) boot: 0 nvs WiFi data 01 02 00009000 00006000 I (70) boot: 1 phy_init RF data 01 01 0000f000 00001000 I (77) boot: 2 factory factory app 00 00 00010000 000e1000 I (85) boot: 3 zb_storage Unknown data 01 81 000f1000 00004000 I (92) boot: 4 zb_fct Unknown data 01 81 000f5000 00000400 I (100) boot: End of partition table I (104) esp_image: segment 0: paddr=00010020 vaddr=42068020 size=104b0h ( 66736) map I (129) esp_image: segment 1: paddr=000204d8 vaddr=40800000 size=07b40h ( 31552) load I (140) esp_image: segment 2: paddr=00028020 vaddr=42000020 size=603c8h (394184) map I (239) esp_image: segment 3: paddr=000883f0 vaddr=40807b40 size=05e88h ( 24200) load I (248) esp_image: segment 4: paddr=0008e280 vaddr=4080d9d0 size=01c98h ( 7320) load I (255) boot: Loaded app from partition at offset 0x10000 I (256) boot: Disabling RNG early entropy source... I (269) cpu_start: Unicore app I (278) cpu_start: Pro cpu start user code I (278) cpu_start: cpu freq: 96000000 Hz I (278) app_init: Application information: I (280) app_init: Project name: HA_customized_switch I (286) app_init: App version: 238b4a9-dirty I (292) app_init: Compile time: Oct 25 2024 10:50:03 I (298) app_init: ELF file SHA256: a1e106b29... I (303) app_init: ESP-IDF: v5.4-dev-3489-g6e5a178b31 I (310) efuse_init: Min chip rev: v0.0 I (314) efuse_init: Max chip rev: v0.99 I (319) efuse_init: Chip rev: v0.1 I (324) heap_init: Initializing. RAM available for dynamic allocation: I (331) heap_init: At 40813E40 len 00039540 (229 KiB): RAM I (337) heap_init: At 4084D380 len 00002B60 (10 KiB): RAM I (345) spi_flash: detected chip: generic I (348) spi_flash: flash io: dio W (352) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header. I (366) sleep_gpio: Configure to isolate all GPIO pins in sleep state I (373) sleep_gpio: Enable automatic switching of GPIO sleep configuration I (380) main_task: Started on CPU0 I (380) main_task: Calling app_main() I (410) phy: phy_version: 310,2, 463a420, Aug 15 2024, 18:52:11 I (420) phy: libbtbb version: a024da6, Aug 15 2024, 18:52:23 I (430) main_task: Returned from app_main() I (440) ESP_HA_ON_OFF_SWITCH: ZDO signal: ZDO Config Ready (0x17), status: ESP_FAIL I (730) gpio: GPIO[9]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:4 I (730) ESP_HA_ON_OFF_SWITCH: Deferred driver initialization successful I (730) ESP_HA_ON_OFF_SWITCH: Joined network successfully (Extended PAN ID: dd:dd:dd:dd:dd:dd:dd:dd, PAN ID: 0x1a62, Channel:11, Short Address: 0x2696) I (780) ESP_HA_ON_OFF_SWITCH: Match desc response: status(0), address(0x0), endpoint(1) I (860) ESP_HA_ON_OFF_SWITCH: Active endpoint response: status(0) and endpoint count(2) I (860) ESP_HA_ON_OFF_SWITCH: Endpoint ID List: 1 I (860) ESP_HA_ON_OFF_SWITCH: Endpoint ID List: 242 I (890) ESP_HA_ON_OFF_SWITCH: 111138 I (930) ESP_HA_ON_OFF_SWITCH: IEEE address: e0:79:8d:ff:fe:bf:0f:af I (990) ESP_HA_ON_OFF_SWITCH: 140 W (1530) ESP_HA_ON_OFF_SWITCH: Receive Zigbee action(0x1005) callback
Since you just said that endpoint 1 may be bound to too many clusters, I have now changed it to 11, but both errors still exist.
Hi @script0803 ,
Since you just said that endpoint 1 may be bound to too many clusters, I have now changed it to 11, but both errors still exist.
It seems there may be a misunderstanding. Based on the reference, the ESP device with the short address 0x2dbc
is sending a bind request to the coordinator (0x0000
). The coordinator responds to 0x2dbc
with a TABLE FULL
status, indicating that there is no available space in the coordinator’s binding table to store the binding information for 0x2dbc
. This issue is not related to 0x2dbc
itself; the solution SHOULD be to increase the binding table size on the coordinator (Sonoff Dongle-E).
Hi @xieqinan ,
But I think the sonoff dongle-e is a very common dongle for connecting zigbee3.0 devices. I tried other zigbee devices and they were all normal. Why is there insufficient space under the esp module? And I haven't bound many clusters. This is very strange.
Have other Zigbee devices attempted to bind their information to the coordinator?
The esp_zigbee_customized_device
example demonstrates the attribute reporting process, so the switch
example needs to bind its information to the light
for the light
to report its attributes. If you don’t have this requirement, consider using a more general example to join the coordinator, such as the on/off light example.
Hi @xieqinan , I will be using electrical measurement and metering cluster. Which example do you recommend I use to start?
I think it is bettter to refer to the temperature sensor example and thermostat example.
Hi @xieqinan ,
I am making some modifications based on the temperature sensor example.
I can now use zigbee2mqtt to see the cluster and attribute I registered normally.
I used an asynchronous function to simulate the data update. But the value of the attribute I read in zigbee2mqtt is always 0.
The following is my code. Can you help me see where the problem is? Thank you very much!
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*
* Zigbee HA_temperature_sensor Example
*
* This example code is in the Public Domain (or CC0 licensed, at your option.)
*
* Unless required by applicable law or agreed to in writing, this
* software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied.
*/
#include "esp_zb_temperature_sensor.h"
#include "temp_sensor_driver.h"
#include "switch_driver.h"
#include "esp_check.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "ha/esp_zigbee_ha_standard.h"
#include "time.h"
#include "stdlib.h"
#if !defined ZB_ED_ROLE
#error Define ZB_ED_ROLE in idf.py menuconfig to compile sensor (End Device) source code.
#endif
static const char *TAG = "ESP_ZB_TEMP_SENSOR";
typedef struct {
uint32_t low; // low 32
uint16_t high; // high 16
} uint48_t;
uint48_t convertToUint48(double value) {
uint64_t intValue = (uint64_t)(value * 1000);
uint48_t result;
result.low = (uint32_t)(intValue & 0xFFFFFFFF);
result.high = (uint16_t)((intValue >> 32) & 0xFFFF);
return result;
}
uint48_t currentSummDelivered;
uint48_t currentSummReceived;
uint16_t voltage;
uint16_t current;
int16_t activePower;
void update_attributes() {
// random value
voltage = ((double)rand() / RAND_MAX) * 12000.0 + 12000.0;
current = ((double)rand() / RAND_MAX) * 10000.0 + 1.0;
activePower = ((double)rand() / RAND_MAX) * 10000.0;
double newDeliveredValue = ((double)rand() / RAND_MAX) * 10.0;
double newReceivedValue = ((double)rand() / RAND_MAX) * 5.0;
// 转换为 uint48_t 类型
currentSummDelivered = convertToUint48(newDeliveredValue);
currentSummReceived = convertToUint48(newReceivedValue);
// ESP_LOGI(TAG, "Updated attributes: Delivered = %f, Received = %f", newDeliveredValue, newReceivedValue);
}
void update_task(void *pvParameters) {
while (1) {
update_attributes();
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
static int16_t zb_temperature_to_s16(float temp)
{
return (int16_t)(temp * 100);
}
static switch_func_pair_t button_func_pair[] = {
{GPIO_INPUT_IO_TOGGLE_SWITCH, SWITCH_ONOFF_TOGGLE_CONTROL}
};
static void esp_app_buttons_handler(switch_func_pair_t *button_func_pair)
{
if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) {
/* Send report attributes command */
esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
report_attr_cmd.attributeID = ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT;
report_attr_cmd.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE;
report_attr_cmd.clusterID = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID;
report_attr_cmd.zcl_basic_cmd.src_endpoint = HA_ESP_SENSOR_ENDPOINT;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_zb_lock_release();
ESP_EARLY_LOGI(TAG, "Send 'report attributes' command");
}
}
static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask)
{
ESP_RETURN_ON_FALSE(esp_zb_bdb_start_top_level_commissioning(mode_mask) == ESP_OK, ,
TAG, "Failed to start Zigbee bdb commissioning");
}
static esp_err_t deferred_driver_init(void)
{
ESP_RETURN_ON_FALSE(switch_driver_init(button_func_pair, PAIR_SIZE(button_func_pair), esp_app_buttons_handler), ESP_FAIL, TAG,
"Failed to initialize switch driver");
return ESP_OK;
}
void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct)
{
uint32_t *p_sg_p = signal_struct->p_app_signal;
esp_err_t err_status = signal_struct->esp_err_status;
esp_zb_app_signal_type_t sig_type = *p_sg_p;
switch (sig_type) {
case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP:
ESP_LOGI(TAG, "Initialize Zigbee stack");
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION);
break;
case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START:
case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT:
if (err_status == ESP_OK) {
ESP_LOGI(TAG, "Deferred driver initialization %s", deferred_driver_init() ? "failed" : "successful");
ESP_LOGI(TAG, "Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non");
if (esp_zb_bdb_is_factory_new()) {
ESP_LOGI(TAG, "Start network steering");
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING);
} else {
ESP_LOGI(TAG, "Device rebooted");
}
} else {
/* commissioning failed */
ESP_LOGW(TAG, "Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status));
}
break;
case ESP_ZB_BDB_SIGNAL_STEERING:
if (err_status == ESP_OK) {
esp_zb_ieee_addr_t extended_pan_id;
esp_zb_get_extended_pan_id(extended_pan_id);
ESP_LOGI(TAG, "Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)",
extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4],
extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], extended_pan_id[0],
esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address());
} else {
ESP_LOGI(TAG, "Network steering was not successful (status: %s)", esp_err_to_name(err_status));
esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000);
}
break;
default:
ESP_LOGI(TAG, "ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type,
esp_err_to_name(err_status));
break;
}
}
static void esp_zb_task(void *pvParameters)
{
/* Initialize Zigbee stack */
esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZED_CONFIG();
esp_zb_init(&zb_nwk_cfg);
uint8_t test_attr;
test_attr = 0;
/* basic cluster create with fully customized */
esp_zb_attribute_list_t *esp_zb_basic_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_BASIC);
esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, MANUFACTURER_NAME);
esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, MODEL_IDENTIFIER);
esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_ZCL_VERSION_ID, &test_attr);
esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID, &test_attr);
esp_zb_cluster_update_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_ZCL_VERSION_ID, &test_attr);
/* electrical_meas cluster create with fully customized */
esp_zb_attribute_list_t *esp_zb_ec_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT);
esp_zb_electrical_meas_cluster_add_attr(esp_zb_ec_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID, &voltage);
esp_zb_electrical_meas_cluster_add_attr(esp_zb_ec_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSCURRENT_ID, ¤t);
esp_zb_electrical_meas_cluster_add_attr(esp_zb_ec_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACTIVE_POWER_ID, &activePower);
esp_zb_electrical_meas_cluster_add_attr(esp_zb_ec_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACVOLTAGE_MULTIPLIER_ID, &VOLTAGE_MULTIPLIER);
esp_zb_electrical_meas_cluster_add_attr(esp_zb_ec_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACVOLTAGE_DIVISOR_ID, &VOLTAGE_DIVISOR);
esp_zb_electrical_meas_cluster_add_attr(esp_zb_ec_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACCURRENT_MULTIPLIER_ID, &CURRENT_MULTIPLIER);
esp_zb_electrical_meas_cluster_add_attr(esp_zb_ec_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACCURRENT_DIVISOR_ID, &CURRENT_DIVISOR);
esp_zb_electrical_meas_cluster_add_attr(esp_zb_ec_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_MULTIPLIER_ID, &ACTIVE_POWER_MULTIPLIER);
esp_zb_electrical_meas_cluster_add_attr(esp_zb_ec_cluster, ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_ACPOWER_DIVISOR_ID, &ACTIVE_POWER_DIVISOR);
/* metering cluster create */
esp_zb_attribute_list_t *esp_zb_meter_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_METERING);
esp_zb_cluster_add_attr(esp_zb_meter_cluster, ESP_ZB_ZCL_CLUSTER_ID_METERING,
ESP_ZB_ZCL_ATTR_METERING_CURRENT_SUMMATION_DELIVERED_ID, ESP_ZB_ZCL_ATTR_TYPE_U48, ESP_ZB_ZCL_ATTR_ACCESS_READ_ONLY | ESP_ZB_ZCL_ATTR_ACCESS_REPORTING, ¤tSummDelivered);
esp_zb_cluster_add_attr(esp_zb_meter_cluster, ESP_ZB_ZCL_CLUSTER_ID_METERING,
ESP_ZB_ZCL_ATTR_METERING_CURRENT_SUMMATION_RECEIVED_ID, ESP_ZB_ZCL_ATTR_TYPE_U48, ESP_ZB_ZCL_ATTR_ACCESS_READ_ONLY | ESP_ZB_ZCL_ATTR_ACCESS_REPORTING, ¤tSummReceived);
/* identify cluster create with fully customized */
esp_zb_attribute_list_t *esp_zb_identify_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY);
esp_zb_identify_cluster_add_attr(esp_zb_identify_cluster, ESP_ZB_ZCL_ATTR_IDENTIFY_IDENTIFY_TIME_ID, &test_attr);
/* create client role of the cluster */
// esp_zb_attribute_list_t *esp_zb_on_off_client_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_ON_OFF);
esp_zb_attribute_list_t *esp_zb_identify_client_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY);
/* create cluster lists for this endpoint */
esp_zb_cluster_list_t *esp_zb_cluster_list = esp_zb_zcl_cluster_list_create();
esp_zb_cluster_list_add_basic_cluster(esp_zb_cluster_list, esp_zb_basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_list_add_identify_cluster(esp_zb_cluster_list, esp_zb_identify_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
// esp_zb_cluster_list_add_on_off_cluster(esp_zb_cluster_list, esp_zb_on_off_client_cluster, ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE);
esp_zb_cluster_list_add_identify_cluster(esp_zb_cluster_list, esp_zb_identify_client_cluster, ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE);
// esp_zb_cluster_list_add_custom_cluster(esp_zb_cluster_list, custom_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_list_add_electrical_meas_cluster(esp_zb_cluster_list, esp_zb_ec_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_cluster_list_add_metering_cluster(esp_zb_cluster_list, esp_zb_meter_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
esp_zb_ep_list_t *esp_zb_ep_list = esp_zb_ep_list_create();
esp_zb_endpoint_config_t endpoint_config = {
.endpoint = HA_ESP_SENSOR_ENDPOINT,
.app_profile_id = ESP_ZB_AF_HA_PROFILE_ID,
.app_device_id = ESP_ZB_HA_CUSTOM_ATTR_DEVICE_ID,
.app_device_version = 0
};
esp_zb_ep_list_add_ep(esp_zb_ep_list, esp_zb_cluster_list, endpoint_config);
esp_zb_device_register(esp_zb_ep_list);
/* Config the reporting info */
esp_zb_zcl_reporting_info_t reporting_info = {
.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV,
.ep = HA_ESP_SENSOR_ENDPOINT,
.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT,
.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE,
.dst.profile_id = ESP_ZB_AF_HA_PROFILE_ID,
.u.send_info.min_interval = 1,
.u.send_info.max_interval = 5,
.u.send_info.def_min_interval = 1,
.u.send_info.def_max_interval = 5,
.u.send_info.delta.u16 = 0,
.attr_id = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID,
.manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC,
};
esp_zb_zcl_update_reporting_info(&reporting_info);
esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK);
ESP_ERROR_CHECK(esp_zb_start(false));
esp_zb_stack_main_loop();
}
void app_main(void)
{
srand(time(NULL));
esp_zb_platform_config_t config = {
.radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(),
.host_config = ESP_ZB_DEFAULT_HOST_CONFIG(),
};
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_zb_platform_config(&config));
/* Start Zigbee stack task */
xTaskCreate(esp_zb_task, "Zigbee_main", 8192, NULL, 5, NULL);
xTaskCreate(update_task, "UpdateTask", 4096, NULL, 5, NULL);
}
Hi @script0803 ,
It seems there’s a misunderstanding regarding the esp_zb_xxx_cluster_add_attr()
API. This API allows users to add an attribute to a cluster and initialize its value, but the attribute is deep-copied into the stack. Therefore, updating voltage
in update_attributes()
will not sync with the attribute in the stack.
You might try using esp_zb_zcl_set_attribute_val()
within update_attributes()
to synchronize the ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID
attribute with the stack.
By the way, there is having a error in esp_app_buttons_handler()
, correct it.
static void esp_app_buttons_handler(switch_func_pair_t *button_func_pair)
{
if (button_func_pair->func == SWITCH_ONOFF_TOGGLE_CONTROL) {
/* Send report attributes command */
esp_zb_zcl_report_attr_cmd_t report_attr_cmd;
report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_ELECTRICAL_MEASUREMENT_RMSVOLTAGE_ID;
report_attr_cmd.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE;
report_attr_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ELECTRICAL_MEASUREMENT;
report_attr_cmd.zcl_basic_cmd.src_endpoint = HA_ESP_SENSOR_ENDPOINT;
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_report_attr_cmd_req(&report_attr_cmd);
esp_zb_lock_release();
ESP_EARLY_LOGI(TAG, "Send 'report attributes' command");
}
}
This works, thank you very much!
Question
When using the example: customized client,
I encountered two incorrect ZDO statuses, 'ESP_ZB_ZDP_STATUS_INSUFFICIENT_SPACE' and 'ESP_ZB_ZDP_STATUS_BINDING_TABLE_FULL'.
Do I need to adjust any settings?
The corresponding log output is as follows: I (349) main_task: Started on CPU0 I (349) main_task: Calling app_main() I (359) phy_init: phy_version 320,348a293,Sep 3 2024,16:33:12 I (399) phy: libbtbb version: 04952fd, Sep 3 2024, 16:33:30 I (409) main_task: Returned from app_main() I (419) ESP_HA_ON_OFF_SWITCH: ZDO signal: ZDO Config Ready (0x17), status: ESP_FAIL I (699) gpio: GPIO[9]| InputEn: 1| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:4 I (699) ESP_HA_ON_OFF_SWITCH: Deferred driver initialization successful I (709) ESP_HA_ON_OFF_SWITCH: Joined network successfully (Extended PAN ID: dd:dd:dd:dd:dd:dd:dd:dd, PAN ID: 0x1a62, Channel:11, Short Address: 0xd41b) I (749) ESP_HA_ON_OFF_SWITCH: Match desc response: status(0), address(0x0), endpoint(1) I (819) ESP_HA_ON_OFF_SWITCH: Active endpoint response: status(0) and endpoint count(2) I (819) ESP_HA_ON_OFF_SWITCH: Endpoint ID List: 1 I (819) ESP_HA_ON_OFF_SWITCH: Endpoint ID List: 242 I (849) ESP_HA_ON_OFF_SWITCH: 111138 I (879) ESP_HA_ON_OFF_SWITCH: IEEE address: e0:79:8d:ff:fe:bf:0f:af I (939) ESP_HA_ON_OFF_SWITCH: 140
Additional context.
No response