Closed matthiasbuettner159 closed 2 months ago
@matthiasbuettner159 ,
Could you please provide the log_i("%d", measured_value);
for me? According to the code above, the value will only be reported when the measured_value
changes by more than delta.u16 = 100
.
@xieqinan ,
the value ranges from 0 to about 1000 in rare cases. However changes between individual measurements are ususally significantly smaller than 100. But I also do not get an updated value at my coordinator if I change the delta to delta.u16 = 1
.
The logs I receive are:
[ 1278][I][Zigbee_LightMeter_Sensor.ino:169] esp_zb_app_signal_handler(): ZDO signal: ZDO Config Ready (0x17), status: ESP_FAIL
[ 1278][I][Zigbee_LightMeter_Sensor.ino:132] esp_zb_app_signal_handler(): Zigbee stack initialized
[ 3649][I][Zigbee_LightMeter_Sensor.ino:138] esp_zb_app_signal_handler(): Start network steering
[ 3650][I][Zigbee_LightMeter_Sensor.ino:139] esp_zb_app_signal_handler(): Device started up in non factory-reset mode
[ 3650][I][Zigbee_LightMeter_Sensor.ino:144] esp_zb_app_signal_handler(): Device rebooted
[ 3651][I][Zigbee_LightMeter_Sensor.ino:114] esp_app_illu_sensor_handler(): Updating illuminance sensor value 3...
[ 3651][I][Zigbee_LightMeter_Sensor.ino:115] esp_app_illu_sensor_handler(): 127
[ 3652][I][Zigbee_LightMeter_Sensor.ino:253] zb_deep_sleep_start(): [ESP_ZB_DEEP_SLEEP] Start one-shot timer for 5s to enter the deep sleep
[ 8653][I][Zigbee_LightMeter_Sensor.ino:260] s_oneshot_timer_callback(): [ESP_ZB_DEEP_SLEEP] Enter deep sleep
with different measurement values, e.g. 14 -> 25 -> 127 -> 145 -> 45 -> etc.
@matthiasbuettner159 ,
Alright, it appears that a bind operation is missing for the attribute report. Could you refer to this example to bind the attribute you expect to send to the coordinator? It is similar to the issue mentioned in https://github.com/espressif/esp-zigbee-sdk/issues/344#issuecomment-2162954461.
You can also try to proactively send the report using esp_zb_zcl_report_attr_cmd_req()
to ensure the Zigbee_LightMeter_Sensor
can receive the report command.
@xieqinan ,
Thanks a lot for your responses and your effort in supporting. I tried fiddling around with the example and your answer in the linked comment.
It is somewhat working now. My solution is to setup the esp_zb_zdo_device_bind_req
in ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT
. The code is as follows:
case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT:
if (err_status == ESP_OK) {
log_i("Start network steering");
log_i("Device started up in %s factory-reset mode", esp_zb_bdb_is_factory_new() ? "" : "non");
if (esp_zb_bdb_is_factory_new()) {
log_i("Start network steering");
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING);
} else {
log_i("Device rebooted");
esp_zb_zdo_bind_req_param_t bind_req;
bind_req.req_dst_addr = esp_zb_get_short_address();
esp_zb_ieee_address_by_short(bind_req.req_dst_addr, bind_req.src_address);
bind_req.src_endp = HA_ESP_SENSOR_ENDPOINT;
bind_req.cluster_id = ESP_ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT;
bind_req.dst_addr_mode = ESP_ZB_ZDO_BIND_DST_ADDR_MODE_64_BIT_EXTENDED;
esp_zb_ieee_address_by_short(0x0000, bind_req.dst_address_u.addr_long);
bind_req.dst_endp = 1;
esp_zb_zdo_device_bind_req(&bind_req, NULL, NULL);
log_i("Update value");
illu_sensor_value_update();
}
} else {
/* commissioning failed */
log_w("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status));
}
break;
This does eventually report the updated value back to my coordinator. However the whole process takes about 7-10 seconds which is quite long for a battery powered device imo and would like to have it shorter (if possible). These are the logs on my coordinator with timestamps for reference:
Debug 2024-06-13 09:21:09 Device '0x543204fffe11dec0' announced itself
Debug 2024-06-13 09:21:11 Retrieving state of '0x543204fffe11dec0' after reconnect
Debug 2024-06-13 09:21:16 Received Zigbee message from '0x543204fffe11dec0', type 'attributeReport', cluster 'msIlluminanceMeasurement', data '{"measuredValue":32}' from endpoint 10 with groupID 0
I also tried proactively using the esp_zb_zcl_report_attr_cmd_req()
, but fail to set it up correctly. This is what I tried adding after the abovementioned illu_sensor_value_update()
call:
esp_zb_zcl_report_attr_cmd_t cmd_req;
esp_zb_ieee_address_by_short(0x0000, cmd_req.zcl_basic_cmd.dst_addr_u.addr_long);
cmd_req.zcl_basic_cmd.dst_endpoint = 1;
cmd_req.zcl_basic_cmd.src_endpoint = HA_ESP_SENSOR_ENDPOINT;
cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
cmd_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT;
cmd_req.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE;
cmd_req.attributeID = ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_ID;
esp_zb_zcl_report_attr_cmd_req(&cmd_req);
I assume I have not fully understand which addresses and values need to be provided to get it to work. When adding this code to my file no updates are reported as before and I receive the following log after about 60s on the sensor device:
[ 68574][I][Zigbee_LightMeter_Sensor.ino:208] esp_zb_app_signal_handler(): ZDO signal: ZDO Device Unavailable (0x3c), status: ESP_OK
@matthiasbuettner159
This does eventually report the updated value back to my coordinator. However the whole process takes about 7-10 seconds which is quite long for a battery powered device imo and would like to have it shorter (if possible).
The report time depends on the configuration of esp_zb_zcl_reporting_info_t reporting_info
. If max_interval = 0
and min_interval != 0xffff
, there will be no periodic reporting, but change-based reporting will still be operational. If you want periodic reports, set max_interval = 1
and min_interval = 0
so that reports will be generated every second. Alternatively, you can call esp_zb_zcl_report_attr_cmd_req()
to send reports proactively.
esp_zb_zcl_report_attr_cmd_t cmd_req;
cmd_req.zcl_basic_cmd.dst_endpoint = 1;
cmd_req.zcl_basic_cmd.src_endpoint = HA_ESP_SENSOR_ENDPOINT;
cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = 0x0000;
cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
cmd_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_ILLUMINANCE_MEASUREMENT;
cmd_req.cluster_role = ESP_ZB_ZCL_CLUSTER_SERVER_ROLE;
cmd_req.attributeID = ESP_ZB_ZCL_ATTR_ILLUMINANCE_MEASUREMENT_MEASURED_VALUE_ID;
esp_zb_zcl_report_attr_cmd_req(&cmd_req);
@xieqinan , Thanks a lot - this did the trick and now my sensor is reporting one value before going back to sleep.
One additional question: How can I add reporting for a second value? I would like to send the current battery voltage alongside the measurement. Trying to add a new attribute to the cluster does not work, (at least it is not showing up on my corrdinator). Do I have to setup a new cluster for this?
@matthiasbuettner159 would it be possible for you to post your complete source somewhere? I am trying to do something similar - and report battery voltage/percentage back via the ESP_ZB_ZCL_CLUSTER_ID_POWER_CONFIG cluster but it does not seem to be working. I am trying to integrate to a Homey Pro.
@matthiasbuettner159 @jrossouw ,
How can I add reporting for a second value?
You can call the esp_zb_scheduler_alarm()
to set a alarm to send esp_zb_zcl_report_attr_cmd_req()
, or refer to this example to configuure the attribute reporting interval.
I would like to send the current battery voltage alongside the measurement. Trying to add a new attribute to the cluster does not work, (at least it is not showing up on my corrdinator). Do I have to setup a new cluster for this?
Yes, you need to add a POWER CONFIG cluster to implement this. Please note that only attributes with REPORT access, as defined by the ZCL specification, can be reported, such as ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID
attribute of POWER CONFIG cluster.
I have started a github project with the aim to share a working example of a temperature sensor that reports temperature, its batttery voltage - as well as having one config parameter that can be set remotely (say for instance to control the sleep period of the device). This sensor will mostly sleep to extend battery life. When it wakes it will take new sensor reading, report and then go back to sleep. The code can be found here:
https://github.com/jrossouw/esp32c6-temp-sensor
I have not tested the code yet. I don't currently have access to my test setup.
I have started with the light sleep example, and updated to add the battery voltage and a temperature sensor. The repository is available here:
https://github.com/jrossouw/esp32c6-zigbee-light
I have a number of issues with this code:
E (8638) ESP_ZIGBEE_COMMAND: esp_zb_zcl_report_attr_cmd_req(310): This attribute: 0x20 is not reportable!
esp_zb_zcl_set_attribute_val(HA_ESP_LIGHT_ENDPOINT, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &temperature, false);
@xieqinan could you please have a quick look and see if I am doing anything stupid? I am a novice as this still.
@jrossouw ,
- The battery voltage claims the attribute is not reportable:
This issue is triggered by the ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID
attribute, which lacks REPORT access. You can refer to the figure below. The ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID
supports the report access.
- The code to update the temperature value crashes with an assertion error:
Please also add the minimum and maximum values for the temperature cluster, as they are mandatory requirements.
@xieqinan thank you for the feedback. The updated code now works perfectly. I have updated my git repository for those who are interested.
@matthiasbuettner159 ,
Do you have any other questions regarding this issue?
@xieqinan I have one more question. I have a custom cluster with a read/write attribute. I can see this cluster in my home automation router, and the router can send attribute updates to it - but I never receive it on the device. I was expecting the function registered via esp_zb_core_action_handler_register to get called? How do i configure the device to listen for these attribute updates? My code to create the cluster: `
// Create custom cluster/attribute list
esp_zb_cluster_list_t *cluster_list = esp_zb_ep_list_get_ep(ep_list, HA_ESP_SENSOR_ENDPOINT);;
esp_zb_attribute_list_t *esp_zb_eshed_cluster = esp_zb_zcl_attr_list_create(ZB_ZCL_CLUSTER_ID_ESHED_TANK);
ESP_ERROR_CHECK(esp_zb_custom_cluster_add_custom_attr(esp_zb_eshed_cluster, ESHED_TANK_DIAMETER_CONFIG_ATTR_ID,
ESP_ZB_ZCL_ATTR_TYPE_16BIT, ESP_ZB_ZCL_ATTR_ACCESS_READ_WRITE, &tankDiameter));
ESP_ERROR_CHECK(esp_zb_custom_cluster_add_custom_attr(esp_zb_eshed_cluster, ESHED_TANK_SENSOR_RANGE_ATTR_ID,
ESP_ZB_ZCL_ATTR_TYPE_8BIT, ESP_ZB_ZCL_ATTR_ACCESS_READ_WRITE, &sensorRange));
ESP_ERROR_CHECK(esp_zb_cluster_list_add_custom_cluster(cluster_list, esp_zb_eshed_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE));
` I also then create a bind request for the cluster.
@jrossouw ,
How do i configure the device to listen for these attribute updates? My code to create the cluster:
Regarding this issue, I believe that you can see the custom cluster user guide as reference, please feel free to discuss the problems you encountered when you read this user guide.
@xieqinan thanks for the feedback - I did manage to get it working. I had incompatible data types between my Automation controller and the end device. Once I corrected that i started receiving the attribute update messages. Thanks for the support.
Closing as the questions are all answered.
Question
I am trying to setup a battery powered zigbee device/sensor with deep sleep to ensure long battery life. However I am struggling to send a new value to the corrdinator after the device wakes up.
I have been trying to follow the temperature sensor example but it does not update the value with the setup reporting mechanism (
esp_zb_zcl_set_attribute_val
andesp_zb_zcl_update_reporting_info
). As alternative I am also struggling to get theesp_zb_zcl_write_attr_cmd_req
command to work, as I do not yet fully understand which parameters are needed and how to aquire thedst_addr_u
anddst_endpoint
values. And I am also not sure which is the proper approach.What I want to achieve is:
Additional question: I also want to meassure the battery level/voltage and send this as well to the coordinator. How can I send multiple values (probably to different endpoints?)?
Thanks a lot for your input :)
Additional context.
This is the source code of my sensor.