Closed renatomotorline closed 2 months ago
@renatomotorline ,
The esp_zb_window_covering_cluster_add_attr()
can be used to add this attribute, and the esp_zb_cluster_update_attr()
can be used to update the attribute before the esp_zb_device_register()
is called.
The esp_zb_zcl_get_attribute()
can be used to get the instance of the attribute after the esp_zb_device_register()
is called. You can change the related value using this instance.
@xieqinan
I already have the attribute added:
esp_zb_window_covering_cluster_add_attr(window_attr_list, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_ID, ¤t_lift_percentage); esp_zb_window_covering_cluster_add_attr(window_attr_list, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_LIFT_ID, &installed_open_limit_lift); esp_zb_window_covering_cluster_add_attr(window_attr_list, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_LIFT_ID, &installed_closed_limit_lift); esp_zb_window_covering_cluster_add_attr(window_attr_list, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_ID, ¤t_position_lift); esp_zb_window_covering_cluster_add_attr(window_attr_list, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_PHYSICAL_CLOSED_LIMIT_LIFT_ID, &physical_closed_limit_lift);
I'm using this example made by @ninoweg
https://github.com/ninoweg/esp-zigbee-sdk/tree/main/examples/esp_zigbee_HA_sample/HA_window_covering
From what I understand the esp_zb_cluster_update_attr()
only updates before the device registers, and is done from the device side. But what I want is to change the attribute from the coordinator side.
@renatomotorline ,
The ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_LIFT_ID (0x0010)
is defined as the READ ONLY access in the ZCL spec, means that it can not be changed by other devices using the general command.
@xieqinan
So if I need to write the best way is to create a custom attribute right?
I'm trying to create a custom attribute
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);
/* Create customized window covering endpoint */
esp_zb_ep_list_t *esp_zb_window_covering_ep = esp_zb_ep_list_create();
esp_zb_endpoint_config_t endpoint_config = {
.endpoint = HA_WINDOW_COVERING_ENDPOINT,
.app_profile_id = ESP_ZB_AF_HA_PROFILE_ID,
.app_device_id = ESP_ZB_HA_WINDOW_COVERING_DEVICE_ID,
.app_device_version = 0,
};
esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create();
/* Create basic cluster */
esp_zb_attribute_list_t *basic_attr_list = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_BASIC);
esp_zb_basic_cluster_add_attr(basic_attr_list, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, modelid);
esp_zb_basic_cluster_add_attr(basic_attr_list, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, manufname);
esp_zb_cluster_list_add_basic_cluster(cluster_list, basic_attr_list, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
/* Create window covering cluster */
esp_zb_attribute_list_t *window_attr_list = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING);
esp_zb_window_covering_cluster_cfg_t config = {
.covering_type = ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_ROLLERSHADE,
.covering_status = ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_OPERATIONAL,
.covering_mode = ESP_ZB_ZCL_ATTR_WINDOW_COVERING_TYPE_MOTOR_IS_RUNNING_IN_MAINTENANCE_MODE,
};
esp_zb_cluster_add_attr(window_attr_list, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_WINDOW_COVERING_TYPE_ID,
ESP_ZB_ZCL_ATTR_TYPE_8BIT_ENUM, ESP_ZB_ZCL_ATTR_ACCESS_READ_ONLY, &config.covering_type);
esp_zb_cluster_add_attr(window_attr_list, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CONFIG_STATUS_ID,
ESP_ZB_ZCL_ATTR_TYPE_8BITMAP, ESP_ZB_ZCL_ATTR_ACCESS_READ_ONLY, &config.covering_status);
esp_zb_cluster_add_attr(window_attr_list, ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_MODE_ID,
ESP_ZB_ZCL_ATTR_TYPE_8BITMAP, ESP_ZB_ZCL_ATTR_ACCESS_READ_WRITE, &config.covering_mode);
uint8_t current_lift_percentage = 0x00;
uint16_t installed_open_limit_lift = 0x0000;
uint16_t installed_closed_limit_lift = 0x1770;
uint16_t physical_closed_limit_lift = 0xffff;
uint16_t current_position_lift = ESP_ZB_ZCL_WINDOW_COVERING_CURRENT_POSITION_LIFT_DEFAULT_VALUE;
esp_zb_window_covering_cluster_add_attr(window_attr_list, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_ID, ¤t_lift_percentage);
esp_zb_window_covering_cluster_add_attr(window_attr_list, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_LIFT_ID, &installed_open_limit_lift);
esp_zb_window_covering_cluster_add_attr(window_attr_list, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_CLOSED_LIMIT_LIFT_ID, &installed_closed_limit_lift);
esp_zb_window_covering_cluster_add_attr(window_attr_list, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_ID, ¤t_position_lift);
esp_zb_window_covering_cluster_add_attr(window_attr_list, ESP_ZB_ZCL_ATTR_WINDOW_COVERING_PHYSICAL_CLOSED_LIMIT_LIFT_ID, &physical_closed_limit_lift);
esp_zb_cluster_list_add_window_covering_cluster(cluster_list, window_attr_list, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
/********** Custom Attribute **********/
esp_zb_attribute_list_t *custom_attr = esp_zb_zcl_attr_list_create(0x8001);
ESP_ERROR_CHECK(esp_zb_custom_cluster_add_custom_attr(custom_attr, 0, ESP_ZB_ZCL_ATTR_TYPE_U16, ESP_ZB_ZCL_ATTR_ACCESS_REPORTING | ESP_ZB_ZCL_ATTR_ACCESS_READ_WRITE, &custom_attribute));
ESP_ERROR_CHECK(esp_zb_cluster_list_add_custom_cluster(cluster_list, custom_attr, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE));
esp_zb_ep_list_add_ep(esp_zb_window_covering_ep, cluster_list, endpoint_config);
esp_zb_device_register(esp_zb_window_covering_ep);
// esp_zb_device_cb_id_handler_register(device_cb);
// esp_zb_raw_command_handler_register(raw_command_handler);
// esp_zb_cli_resp_handler_register(esp_zb_cli_agent_handler);
esp_zb_core_action_handler_register(zb_action_handler);
esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK);
ESP_ERROR_CHECK(esp_zb_start(false));
esp_zb_main_loop_iteration();
}
And send from the coordinator
esp_zb_zcl_custom_cluster_cmd_req_t cmd_req;
cmd_req.zcl_basic_cmd.src_endpoint = HA_ENDPOINT;
cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT;
cmd_req.profile_id = ESP_ZB_AF_HA_PROFILE_ID;
cmd_req.cluster_id = 0x8001;
cmd_req.custom_cmd_id = 0;
cmd_req.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_SRV;
cmd_req.data.type = ESP_ZB_ZCL_ATTR_TYPE_U16;
cmd_req.data.size = sizeof(uint16_t);
cmd_req.data.value = to_open ? &position_up : &position_down;
to_open = !to_open;
esp_zb_lock_acquire(portMAX_DELAY);
uint8_t seq = esp_zb_zcl_custom_cluster_cmd_req(&cmd_req);
esp_zb_lock_release();
But don't receive anything in the zb_action_handler
of the end device. What I'm doing wrong?
Ok now I'm receiving it, I added esp_zb_zdo_match_cluster
when the end device is commissioned.
But I don't receive any report from the end device in the coordinator.
End device:
esp_zb_lock_acquire(portMAX_DELAY);
esp_zb_zcl_set_attribute_val(HA_WINDOW_COVERING_ENDPOINT,
ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING,
ESP_ZB_ZCL_CLUSTER_SERVER_ROLE,
ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_PERCENTAGE_ID,
&lift_percentage,
false);
esp_zb_zcl_set_attribute_val(HA_WINDOW_COVERING_ENDPOINT,
ESP_ZB_ZCL_CLUSTER_ID_WINDOW_COVERING,
ESP_ZB_ZCL_CLUSTER_SERVER_ROLE,
ESP_ZB_ZCL_ATTR_WINDOW_COVERING_CURRENT_POSITION_LIFT_ID,
&lift_value,
false);
esp_zb_zcl_status_t status = esp_zb_zcl_set_attribute_val(HA_WINDOW_COVERING_ENDPOINT,
0x8001,
ESP_ZB_ZCL_CLUSTER_SERVER_ROLE,
0,
&custom_attribute,
false);
ESP_LOGE(TAG, "Status: 0x%02x", status);
esp_zb_lock_release();
Coordinator:
static esp_zb_cluster_list_t *custom_window_covering_clusters_create(esp_zb_window_covering_cfg_t *window_covering) {
esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create();
esp_zb_attribute_list_t *basic_cluster = esp_zb_basic_cluster_create(&(window_covering->basic_cfg));
ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, MANUFACTURER_NAME));
ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, MODEL_IDENTIFIER));
ESP_ERROR_CHECK(esp_zb_cluster_list_add_basic_cluster(cluster_list, basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE));
ESP_ERROR_CHECK(esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_identify_cluster_create(&(window_covering->identify_cfg)), ESP_ZB_ZCL_CLUSTER_SERVER_ROLE));
ESP_ERROR_CHECK(esp_zb_cluster_list_add_identify_cluster(cluster_list, esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE));
ESP_ERROR_CHECK(esp_zb_cluster_list_add_window_covering_cluster(cluster_list, esp_zb_window_covering_cluster_create(NULL), ESP_ZB_ZCL_CLUSTER_CLIENT_ROLE));
esp_zb_attribute_list_t *custom_attr = esp_zb_zcl_attr_list_create(0x8001);
ESP_ERROR_CHECK(esp_zb_custom_cluster_add_custom_attr(custom_attr, 0, ESP_ZB_ZCL_ATTR_TYPE_U16, ESP_ZB_ZCL_ATTR_ACCESS_REPORTING | ESP_ZB_ZCL_ATTR_ACCESS_READ_WRITE, &custom_attribute));
ESP_ERROR_CHECK(esp_zb_cluster_list_add_custom_cluster(cluster_list, custom_attr, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE));
return cluster_list;
}
static void custom_window_covering_ep_create(esp_zb_ep_list_t *ep_list, uint8_t endpoint_id, esp_zb_window_covering_cfg_t *window_covering) {
esp_zb_endpoint_config_t endpoint_config = {
.endpoint = endpoint_id,
.app_profile_id = ESP_ZB_AF_HA_PROFILE_ID,
.app_device_id = ESP_ZB_HA_WINDOW_COVERING_DEVICE_ID,
.app_device_version = 0};
esp_zb_ep_list_add_ep(ep_list, custom_window_covering_clusters_create(window_covering), endpoint_config);
}
static void esp_zb_task(void *pvParameters) {
// Initialize Zigbee stack
esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZC_CONFIG();
esp_zb_init(&zb_nwk_cfg);
// Create endpoint list
esp_zb_ep_list_t *ep_list = esp_zb_ep_list_create();
// Create window covering
esp_zb_window_covering_cfg_t window_covering_cfg = ESP_ZB_DEFAULT_WINDOW_COVERING_CONFIG();
custom_window_covering_ep_create(ep_list, HA_ENDPOINT, &window_covering_cfg);
// Register the device
esp_zb_device_register(ep_list);
esp_zb_core_action_handler_register(zb_action_handler);
esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK);
ESP_ERROR_CHECK(esp_zb_start(false));
esp_zb_main_loop_iteration();
}
@renatomotorline ,
But I don't receive any report from the end device in the coordinator.
If you expect the end device to report the custom attribute to the coordinator, you need to add a binding and configure the report operation on the end device side so that the end device knows the report's destination. These operations can refer to the customized switch example. By the way, the custom cluster SHOULD be the client role on the coordinator.
@renatomotorline please reopen if any follow up questions.
Question
I'm able to send OPEN and CLOSE from the coordinator using the
esp_zb_zcl_window_covering_cluster_send_cmd_req
function, which supports these commands:But I also want to change the settings. How can I change for example the
ESP_ZB_ZCL_ATTR_WINDOW_COVERING_INSTALLED_OPEN_LIMIT_LIFT_ID
?Additional context.
No response