diff --git a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino index 7cdf45ef711..6f5934f791d 100644 --- a/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino +++ b/libraries/Zigbee/examples/Zigbee_Thermostat/Zigbee_Thermostat.ino @@ -34,7 +34,8 @@ #include "Zigbee.h" /* Zigbee thermostat configuration */ -#define THERMOSTAT_ENDPOINT_NUMBER 5 +#define THERMOSTAT_ENDPOINT_NUMBER 1 +#define USE_RECEIVE_TEMP_WITH_SOURCE 1 uint8_t button = BOOT_PIN; ZigbeeThermostat zbThermostat = ZigbeeThermostat(THERMOSTAT_ENDPOINT_NUMBER); @@ -48,13 +49,28 @@ float sensor_tolerance; struct tm timeinfo = {}; // Time structure for Time cluster /****************** Temperature sensor handling *******************/ -void recieveSensorTemp(float temperature) { +#if USE_RECEIVE_TEMP_WITH_SOURCE == 0 +void receiveSensorTemp(float temperature) { Serial.printf("Temperature sensor value: %.2f°C\n", temperature); sensor_temp = temperature; } +#else +void receiveSensorTempWithSource(float temperature, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) { + if (src_address.addr_type == ESP_ZB_ZCL_ADDR_TYPE_SHORT) { + Serial.printf("Temperature sensor value: %.2f°C from endpoint %d, address 0x%04x\n", temperature, src_endpoint, src_address.u.short_addr); + } else { + Serial.printf( + "Temperature sensor value: %.2f°C from endpoint %d, address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", temperature, src_endpoint, + src_address.u.ieee_addr[7], src_address.u.ieee_addr[6], src_address.u.ieee_addr[5], src_address.u.ieee_addr[4], src_address.u.ieee_addr[3], + src_address.u.ieee_addr[2], src_address.u.ieee_addr[1], src_address.u.ieee_addr[0] + ); + } + sensor_temp = temperature; +} +#endif -void recieveSensorConfig(float min_temp, float max_temp, float tolerance) { - Serial.printf("Temperature sensor settings: min %.2f°C, max %.2f°C, tolerance %.2f°C\n", min_temp, max_temp, tolerance); +void receiveSensorConfig(float min_temp, float max_temp, float tolerance) { + Serial.printf("Temperature sensor config: min %.2f°C, max %.2f°C, tolerance %.2f°C\n", min_temp, max_temp, tolerance); sensor_min_temp = min_temp; sensor_max_temp = max_temp; sensor_tolerance = tolerance; @@ -66,9 +82,15 @@ void setup() { // Init button switch pinMode(button, INPUT_PULLUP); - // Set callback functions for temperature and configuration receive - zbThermostat.onTempRecieve(recieveSensorTemp); - zbThermostat.onConfigRecieve(recieveSensorConfig); +// Set callback function for receiving temperature from sensor - Use only one option +#if USE_RECEIVE_TEMP_WITH_SOURCE == 0 + zbThermostat.onTempReceive(receiveSensorTemp); // If you bound only one sensor or you don't need to know the source of the temperature +#else + zbThermostat.onTempReceiveWithSource(receiveSensorTempWithSource); +#endif + + // Set callback function for receiving sensor configuration + zbThermostat.onConfigReceive(receiveSensorConfig); //Optional: set Zigbee device name and model zbThermostat.setManufacturerAndModel("Espressif", "ZigbeeThermostat"); @@ -107,19 +129,30 @@ void setup() { Serial.println(); - // Get temperature sensor configuration - zbThermostat.getSensorSettings(); + // Get temperature sensor configuration for all bound sensors by endpoint number and address + std::list boundSensors = zbThermostat.getBoundDevices(); + for (const auto &device : boundSensors) { + Serial.println("--------------------------------"); + if (device->short_addr == 0x0000 || device->short_addr == 0xFFFF) { //End devices never have 0x0000 short address or 0xFFFF group address + Serial.printf( + "Device on endpoint %d, IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\r\n", device->endpoint, device->ieee_addr[7], device->ieee_addr[6], + device->ieee_addr[5], device->ieee_addr[4], device->ieee_addr[3], device->ieee_addr[2], device->ieee_addr[1], device->ieee_addr[0] + ); + zbThermostat.getSensorSettings(device->endpoint, device->ieee_addr); + } else { + Serial.printf("Device on endpoint %d, short address: 0x%x\r\n", device->endpoint, device->short_addr); + zbThermostat.getSensorSettings(device->endpoint, device->short_addr); + } + } } void loop() { // Handle button switch in loop() if (digitalRead(button) == LOW) { // Push button pressed - // Key debounce handling while (digitalRead(button) == LOW) { delay(50); } - // Set reporting interval for temperature sensor zbThermostat.setTemperatureReporting(0, 10, 2); } @@ -130,5 +163,6 @@ void loop() { last_print = millis(); int temp_percent = (int)((sensor_temp - sensor_min_temp) / (sensor_max_temp - sensor_min_temp) * 100); Serial.printf("Loop temperature info: %.2f°C (%d %%)\n", sensor_temp, temp_percent); + zbThermostat.printBoundDevices(Serial); } } diff --git a/libraries/Zigbee/keywords.txt b/libraries/Zigbee/keywords.txt index 4d4cd7d0606..5ce1e8f6f51 100644 --- a/libraries/Zigbee/keywords.txt +++ b/libraries/Zigbee/keywords.txt @@ -107,6 +107,7 @@ setLightColor KEYWORD2 # ZigbeeThermostat onTempRecieve KEYWORD2 onConfigRecieve KEYWORD2 +onTempReceiveWithSource KEYWORD2 getTemperature KEYWORD2 getSensorSettings KEYWORD2 setTemperatureReporting KEYWORD2 @@ -191,4 +192,4 @@ ZIGBEE_DEFAULT_COORDINATOR_CONFIG LITERAL1 ZIGBEE_DEFAULT_RADIO_CONFIG LITERAL1 ZIGBEE_DEFAULT_UART_RCP_RADIO_CONFIG LITERAL1 ZIGBEE_DEFAULT_HOST_CONFIG LITERAL1 -ZB_ARRAY_LENTH LITERAL1 +ZB_ARRAY_LENGHT LITERAL1 diff --git a/libraries/Zigbee/src/ZigbeeEP.cpp b/libraries/Zigbee/src/ZigbeeEP.cpp index 1d3df126ce8..efddbdd0368 100644 --- a/libraries/Zigbee/src/ZigbeeEP.cpp +++ b/libraries/Zigbee/src/ZigbeeEP.cpp @@ -145,7 +145,7 @@ bool ZigbeeEP::setBatteryVoltage(uint8_t voltage) { bool ZigbeeEP::reportBatteryPercentage() { /* Send report attributes command */ - esp_zb_zcl_report_attr_cmd_t report_attr_cmd; + esp_zb_zcl_report_attr_cmd_t report_attr_cmd = {0}; report_attr_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; report_attr_cmd.attributeID = ESP_ZB_ZCL_ATTR_POWER_CONFIG_BATTERY_PERCENTAGE_REMAINING_ID; report_attr_cmd.direction = ESP_ZB_ZCL_CMD_DIRECTION_TO_CLI; @@ -166,7 +166,7 @@ bool ZigbeeEP::reportBatteryPercentage() { char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) { /* Read peer Manufacture Name & Model Identifier */ - esp_zb_zcl_read_attr_cmd_t read_req; + esp_zb_zcl_read_attr_cmd_t read_req = {0}; if (short_addr != 0) { read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; @@ -183,7 +183,7 @@ char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_i uint16_t attributes[] = { ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, }; - read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_number = ZB_ARRAY_LENGHT(attributes); read_req.attr_field = attributes; if (_read_manufacturer != NULL) { @@ -204,7 +204,7 @@ char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_i char *ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr) { /* Read peer Manufacture Name & Model Identifier */ - esp_zb_zcl_read_attr_cmd_t read_req; + esp_zb_zcl_read_attr_cmd_t read_req = {0}; if (short_addr != 0) { read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; @@ -221,7 +221,7 @@ char *ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_add uint16_t attributes[] = { ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, }; - read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_number = ZB_ARRAY_LENGHT(attributes); read_req.attr_field = attributes; if (_read_model != NULL) { @@ -375,7 +375,7 @@ bool ZigbeeEP::setTimezone(int32_t gmt_offset) { tm ZigbeeEP::getTime(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ieee_addr) { /* Read peer time */ - esp_zb_zcl_read_attr_cmd_t read_req; + esp_zb_zcl_read_attr_cmd_t read_req = {0}; if (short_addr >= 0) { read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; @@ -386,7 +386,7 @@ tm ZigbeeEP::getTime(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ie } uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TIME_TIME_ID}; - read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_number = ZB_ARRAY_LENGHT(attributes); read_req.attr_field = attributes; read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TIME; @@ -427,7 +427,7 @@ tm ZigbeeEP::getTime(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ie int32_t ZigbeeEP::getTimezone(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_addr_t ieee_addr) { /* Read peer timezone */ - esp_zb_zcl_read_attr_cmd_t read_req; + esp_zb_zcl_read_attr_cmd_t read_req = {0}; if (short_addr >= 0) { read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; @@ -438,7 +438,7 @@ int32_t ZigbeeEP::getTimezone(uint8_t endpoint, int32_t short_addr, esp_zb_ieee_ } uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TIME_TIME_ZONE_ID}; - read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_number = ZB_ARRAY_LENGHT(attributes); read_req.attr_field = attributes; read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TIME; @@ -543,7 +543,7 @@ static void findOTAServer(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t } void ZigbeeEP::requestOTAUpdate() { - esp_zb_zdo_match_desc_req_param_t req; + esp_zb_zdo_match_desc_req_param_t req = {0}; uint16_t cluster_list[] = {ESP_ZB_ZCL_CLUSTER_ID_OTA_UPGRADE}; /* Match the OTA server of coordinator */ diff --git a/libraries/Zigbee/src/ZigbeeEP.h b/libraries/Zigbee/src/ZigbeeEP.h index fe22f31faaf..a3217cbd066 100644 --- a/libraries/Zigbee/src/ZigbeeEP.h +++ b/libraries/Zigbee/src/ZigbeeEP.h @@ -12,7 +12,7 @@ #define ZB_CMD_TIMEOUT 10000 // 10 seconds #define OTA_UPGRADE_QUERY_INTERVAL (1 * 60) // 1 hour = 60 minutes -#define ZB_ARRAY_LENTH(arr) (sizeof(arr) / sizeof(arr[0])) +#define ZB_ARRAY_LENGHT(arr) (sizeof(arr) / sizeof(arr[0])) #define RGB_TO_XYZ(r, g, b, X, Y, Z) \ { \ @@ -131,7 +131,7 @@ class ZigbeeEP { // list of all handlers function calls, to be override by EPs implementation virtual void zbAttributeSet(const esp_zb_zcl_set_attr_value_message_t *message) {}; - virtual void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) {}; + virtual void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) {}; virtual void zbReadBasicCluster(const esp_zb_zcl_attribute_t *attribute); //already implemented virtual void zbIdentify(const esp_zb_zcl_set_attr_value_message_t *message); virtual void zbWindowCoveringMovementCmd(const esp_zb_zcl_window_covering_movement_message_t *message) {}; diff --git a/libraries/Zigbee/src/ZigbeeHandlers.cpp b/libraries/Zigbee/src/ZigbeeHandlers.cpp index eeeb1e8013a..5d54e459058 100644 --- a/libraries/Zigbee/src/ZigbeeHandlers.cpp +++ b/libraries/Zigbee/src/ZigbeeHandlers.cpp @@ -108,7 +108,9 @@ static esp_err_t zb_attribute_reporting_handler(const esp_zb_zcl_report_attr_mes // List through all Zigbee EPs and call the callback function, with the message for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { if (message->dst_endpoint == (*it)->getEndpoint()) { - (*it)->zbAttributeRead(message->cluster, &message->attribute); //method zbAttributeRead must be implemented in specific EP class + (*it)->zbAttributeRead( + message->cluster, &message->attribute, message->src_endpoint, message->src_address + ); //method zbAttributeRead must be implemented in specific EP class } } return ESP_OK; @@ -142,7 +144,9 @@ static esp_err_t zb_cmd_read_attr_resp_handler(const esp_zb_zcl_cmd_read_attr_re } else if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_TIME) { (*it)->zbReadTimeCluster(&variable->attribute); //method zbReadTimeCluster implemented in the common EP class } else { - (*it)->zbAttributeRead(message->info.cluster, &variable->attribute); //method zbAttributeRead must be implemented in specific EP class + (*it)->zbAttributeRead( + message->info.cluster, &variable->attribute, message->info.src_endpoint, message->info.src_address + ); //method zbAttributeRead must be implemented in specific EP class } } variable = variable->next; diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp index 935d638324f..f795ed1a3c8 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp @@ -53,7 +53,7 @@ void ZigbeeColorDimmerSwitch::findCb(esp_zb_zdp_status_t zdo_status, uint16_t ad ZigbeeColorDimmerSwitch *instance = static_cast(user_ctx); if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_d("Found light endpoint"); - esp_zb_zdo_bind_req_param_t bind_req; + esp_zb_zdo_bind_req_param_t bind_req = {0}; zb_device_params_t *light = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); light->endpoint = endpoint; light->short_addr = addr; @@ -97,7 +97,7 @@ void ZigbeeColorDimmerSwitch::findEndpoint(esp_zb_zdo_match_desc_req_param_t *cm // Methods to control the light void ZigbeeColorDimmerSwitch::lightToggle() { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; @@ -112,7 +112,7 @@ void ZigbeeColorDimmerSwitch::lightToggle() { void ZigbeeColorDimmerSwitch::lightToggle(uint16_t group_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -128,7 +128,7 @@ void ZigbeeColorDimmerSwitch::lightToggle(uint16_t group_addr) { void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -145,7 +145,7 @@ void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; @@ -165,7 +165,7 @@ void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t i void ZigbeeColorDimmerSwitch::lightOn() { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; @@ -180,7 +180,7 @@ void ZigbeeColorDimmerSwitch::lightOn() { void ZigbeeColorDimmerSwitch::lightOn(uint16_t group_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -196,7 +196,7 @@ void ZigbeeColorDimmerSwitch::lightOn(uint16_t group_addr) { void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -213,7 +213,7 @@ void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; @@ -233,7 +233,7 @@ void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_ void ZigbeeColorDimmerSwitch::lightOff() { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; @@ -248,7 +248,7 @@ void ZigbeeColorDimmerSwitch::lightOff() { void ZigbeeColorDimmerSwitch::lightOff(uint16_t group_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -264,7 +264,7 @@ void ZigbeeColorDimmerSwitch::lightOff(uint16_t group_addr) { void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -281,7 +281,7 @@ void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; @@ -301,7 +301,7 @@ void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee void ZigbeeColorDimmerSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant) { if (_is_bound) { - esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req; + esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.effect_id = effect_id; @@ -317,7 +317,7 @@ void ZigbeeColorDimmerSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effe void ZigbeeColorDimmerSwitch::lightOnWithSceneRecall() { if (_is_bound) { - esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req; + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; log_v("Sending 'light on with scene recall' command"); @@ -331,7 +331,7 @@ void ZigbeeColorDimmerSwitch::lightOnWithSceneRecall() { void ZigbeeColorDimmerSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off) { if (_is_bound) { - esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req; + esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_control = on_off_control; //TODO: Test how it works, then maybe change API @@ -348,7 +348,7 @@ void ZigbeeColorDimmerSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16 void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level) { if (_is_bound) { - esp_zb_zcl_move_to_level_cmd_t cmd_req; + esp_zb_zcl_move_to_level_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.level = level; @@ -364,7 +364,7 @@ void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level) { void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint16_t group_addr) { if (_is_bound) { - esp_zb_zcl_move_to_level_cmd_t cmd_req; + esp_zb_zcl_move_to_level_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -381,7 +381,7 @@ void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint16_t group_addr) void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint8_t endpoint, uint16_t short_addr) { if (_is_bound) { - esp_zb_zcl_move_to_level_cmd_t cmd_req; + esp_zb_zcl_move_to_level_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -399,7 +399,7 @@ void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint8_t endpoint, uin void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { if (_is_bound) { - esp_zb_zcl_move_to_level_cmd_t cmd_req; + esp_zb_zcl_move_to_level_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; @@ -422,7 +422,7 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t if (_is_bound) { espXyColor_t xy_color = espRgbToXYColor(red, green, blue); - esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + esp_zb_zcl_color_move_to_color_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.color_x = xy_color.x; @@ -441,7 +441,7 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t if (_is_bound) { espXyColor_t xy_color = espRgbToXYColor(red, green, blue); - esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + esp_zb_zcl_color_move_to_color_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -461,7 +461,7 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t if (_is_bound) { espXyColor_t xy_color = espRgbToXYColor(red, green, blue); - esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + esp_zb_zcl_color_move_to_color_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -482,7 +482,7 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t if (_is_bound) { espXyColor_t xy_color = espRgbToXYColor(red, green, blue); - esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + esp_zb_zcl_color_move_to_color_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp index 38fd7d370fb..68e7a7430cc 100644 --- a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp @@ -52,7 +52,7 @@ void ZigbeeSwitch::findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t ZigbeeSwitch *instance = static_cast(user_ctx); if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_d("Found light endpoint"); - esp_zb_zdo_bind_req_param_t bind_req; + esp_zb_zdo_bind_req_param_t bind_req = {0}; zb_device_params_t *light = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); light->endpoint = endpoint; light->short_addr = addr; @@ -94,7 +94,7 @@ void ZigbeeSwitch::findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { // Methods to control the light void ZigbeeSwitch::lightToggle() { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; @@ -109,7 +109,7 @@ void ZigbeeSwitch::lightToggle() { void ZigbeeSwitch::lightToggle(uint16_t group_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -125,7 +125,7 @@ void ZigbeeSwitch::lightToggle(uint16_t group_addr) { void ZigbeeSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -142,7 +142,7 @@ void ZigbeeSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) { void ZigbeeSwitch::lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; @@ -162,7 +162,7 @@ void ZigbeeSwitch::lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { void ZigbeeSwitch::lightOn() { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; @@ -177,7 +177,7 @@ void ZigbeeSwitch::lightOn() { void ZigbeeSwitch::lightOn(uint16_t group_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -193,7 +193,7 @@ void ZigbeeSwitch::lightOn(uint16_t group_addr) { void ZigbeeSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -210,7 +210,7 @@ void ZigbeeSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { void ZigbeeSwitch::lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; @@ -230,7 +230,7 @@ void ZigbeeSwitch::lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { void ZigbeeSwitch::lightOff() { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; @@ -245,7 +245,7 @@ void ZigbeeSwitch::lightOff() { void ZigbeeSwitch::lightOff(uint16_t group_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; @@ -261,7 +261,7 @@ void ZigbeeSwitch::lightOff(uint16_t group_addr) { void ZigbeeSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; @@ -278,7 +278,7 @@ void ZigbeeSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { void ZigbeeSwitch::lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { if (_is_bound) { - esp_zb_zcl_on_off_cmd_t cmd_req; + esp_zb_zcl_on_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.zcl_basic_cmd.dst_endpoint = endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; @@ -298,7 +298,7 @@ void ZigbeeSwitch::lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { void ZigbeeSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant) { if (_is_bound) { - esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req; + esp_zb_zcl_on_off_off_with_effect_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.effect_id = effect_id; @@ -314,7 +314,7 @@ void ZigbeeSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant) void ZigbeeSwitch::lightOnWithSceneRecall() { if (_is_bound) { - esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req; + esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; log_v("Sending 'light on with scene recall' command"); @@ -327,7 +327,7 @@ void ZigbeeSwitch::lightOnWithSceneRecall() { } void ZigbeeSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off) { if (_is_bound) { - esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req; + esp_zb_zcl_on_off_on_with_timed_off_cmd_t cmd_req = {0}; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.on_off_control = on_off_control; //TODO: Test how it works, then maybe change API diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp index 633a60d0ff9..f3bfd7d981b 100644 --- a/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.cpp @@ -65,7 +65,7 @@ void ZigbeeThermostat::findCb(esp_zb_zdp_status_t zdo_status, uint16_t addr, uin ZigbeeThermostat *instance = static_cast(user_ctx); if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { log_i("Found temperature sensor"); - esp_zb_zdo_bind_req_param_t bind_req; + esp_zb_zdo_bind_req_param_t bind_req = {0}; /* Store the information of the remote device */ zb_device_params_t *sensor = (zb_device_params_t *)malloc(sizeof(zb_device_params_t)); sensor->endpoint = endpoint; @@ -115,31 +115,38 @@ void ZigbeeThermostat::findEndpoint(esp_zb_zdo_match_desc_req_param_t *param) { esp_zb_zdo_match_cluster(param, ZigbeeThermostat::findCbWrapper, this); } -void ZigbeeThermostat::zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) { +void ZigbeeThermostat::zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) { static uint8_t read_config = 0; if (cluster_id == ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT) { if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_S16) { int16_t value = attribute->data.value ? *(int16_t *)attribute->data.value : 0; - if (_on_temp_recieve) { - _on_temp_recieve(zb_s16_to_temperature(value)); + if (_on_temp_receive) { + _on_temp_receive(zb_s16_to_temperature(value)); + } + if (_on_temp_receive_with_source) { + _on_temp_receive_with_source(zb_s16_to_temperature(value), src_endpoint, src_address); } } if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_S16) { int16_t min_value = attribute->data.value ? *(int16_t *)attribute->data.value : 0; _min_temp = zb_s16_to_temperature(min_value); read_config++; + log_d("Received min temperature: %.2f°C from endpoint %d", _min_temp, src_endpoint); } if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_S16) { int16_t max_value = attribute->data.value ? *(int16_t *)attribute->data.value : 0; _max_temp = zb_s16_to_temperature(max_value); read_config++; + log_d("Received max temperature: %.2f°C from endpoint %d", _max_temp, src_endpoint); } if (attribute->id == ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID && attribute->data.type == ESP_ZB_ZCL_ATTR_TYPE_U16) { uint16_t tolerance = attribute->data.value ? *(uint16_t *)attribute->data.value : 0; _tolerance = 1.0 * tolerance / 100; read_config++; + log_d("Received tolerance: %.2f°C from endpoint %d", _tolerance, src_endpoint); } if (read_config == 3) { + log_d("All config attributes processed"); read_config = 0; xSemaphoreGive(lock); } @@ -147,14 +154,14 @@ void ZigbeeThermostat::zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_att } void ZigbeeThermostat::getTemperature() { - /* Send "read attributes" command to the bound sensor */ - esp_zb_zcl_read_attr_cmd_t read_req; + /* Send "read attributes" command to all bound sensors */ + esp_zb_zcl_read_attr_cmd_t read_req = {0}; read_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; read_req.zcl_basic_cmd.src_endpoint = _endpoint; read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID}; - read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_number = ZB_ARRAY_LENGHT(attributes); read_req.attr_field = attributes; log_i("Sending 'read temperature' command"); @@ -163,9 +170,68 @@ void ZigbeeThermostat::getTemperature() { esp_zb_lock_release(); } +void ZigbeeThermostat::getTemperature(uint16_t group_addr) { + /* Send "read attributes" command to the group */ + esp_zb_zcl_read_attr_cmd_t read_req = {0}; + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + + uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID}; + read_req.attr_number = ZB_ARRAY_LENGHT(attributes); + read_req.attr_field = attributes; + + log_i("Sending 'read temperature' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); +} + +void ZigbeeThermostat::getTemperature(uint8_t endpoint, uint16_t short_addr) { + /* Send "read attributes" command to specific endpoint */ + esp_zb_zcl_read_attr_cmd_t read_req = {0}; + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + + uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID}; + read_req.attr_number = ZB_ARRAY_LENGHT(attributes); + read_req.attr_field = attributes; + + log_i("Sending 'read temperature' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); +} + +void ZigbeeThermostat::getTemperature(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + /* Send "read attributes" command to specific endpoint */ + esp_zb_zcl_read_attr_cmd_t read_req = {0}; + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + + uint16_t attributes[] = {ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID}; + read_req.attr_number = ZB_ARRAY_LENGHT(attributes); + read_req.attr_field = attributes; + + log_i( + "Sending 'read temperature' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], + ieee_addr[5], ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0] + ); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); +} + void ZigbeeThermostat::getSensorSettings() { - /* Send "read attributes" command to the bound sensor */ - esp_zb_zcl_read_attr_cmd_t read_req; + /* Send "read attributes" command to all bound sensors */ + esp_zb_zcl_read_attr_cmd_t read_req = {0}; read_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; read_req.zcl_basic_cmd.src_endpoint = _endpoint; read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; @@ -173,10 +239,102 @@ void ZigbeeThermostat::getSensorSettings() { uint16_t attributes[] = { ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID }; - read_req.attr_number = ZB_ARRAY_LENTH(attributes); + read_req.attr_number = ZB_ARRAY_LENGHT(attributes); read_req.attr_field = attributes; - log_i("Sending 'read temperature' command"); + log_i("Sending 'read sensor settings' command"); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + + //Take semaphore to wait for response of all attributes + if (xSemaphoreTake(lock, ZB_CMD_TIMEOUT) != pdTRUE) { + log_e("Error while reading attributes"); + return; + } else { + //Call the callback function when all attributes are read + _on_config_receive(_min_temp, _max_temp, _tolerance); + } +} + +void ZigbeeThermostat::getSensorSettings(uint16_t group_addr) { + /* Send "read attributes" command to the group */ + esp_zb_zcl_read_attr_cmd_t read_req = {0}; + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + + uint16_t attributes[] = { + ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID + }; + read_req.attr_number = ZB_ARRAY_LENGHT(attributes); + read_req.attr_field = attributes; + + log_i("Sending 'read sensor settings' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + + //Take semaphore to wait for response of all attributes + if (xSemaphoreTake(lock, ZB_CMD_TIMEOUT) != pdTRUE) { + log_e("Error while reading attributes"); + return; + } else { + //Call the callback function when all attributes are read + _on_config_receive(_min_temp, _max_temp, _tolerance); + } +} + +void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, uint16_t short_addr) { + /* Send "read attributes" command to specific endpoint */ + esp_zb_zcl_read_attr_cmd_t read_req = {0}; + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + + uint16_t attributes[] = { + ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID + }; + read_req.attr_number = ZB_ARRAY_LENGHT(attributes); + read_req.attr_field = attributes; + + log_i("Sending 'read sensor settings' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); + + //Take semaphore to wait for response of all attributes + if (xSemaphoreTake(lock, ZB_CMD_TIMEOUT) != pdTRUE) { + log_e("Error while reading attributes"); + return; + } else { + //Call the callback function when all attributes are read + _on_config_receive(_min_temp, _max_temp, _tolerance); + } +} + +void ZigbeeThermostat::getSensorSettings(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + /* Send "read attributes" command to specific endpoint */ + esp_zb_zcl_read_attr_cmd_t read_req = {0}; + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + read_req.zcl_basic_cmd.src_endpoint = _endpoint; + read_req.zcl_basic_cmd.dst_endpoint = endpoint; + read_req.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + + uint16_t attributes[] = { + ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_TOLERANCE_ID + }; + read_req.attr_number = ZB_ARRAY_LENGHT(attributes); + read_req.attr_field = attributes; + + log_i( + "Sending 'read sensor settings' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], + ieee_addr[5], ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0] + ); esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_read_attr_cmd_req(&read_req); esp_zb_lock_release(); @@ -187,13 +345,13 @@ void ZigbeeThermostat::getSensorSettings() { return; } else { //Call the callback function when all attributes are read - _on_config_recieve(_min_temp, _max_temp, _tolerance); + _on_config_receive(_min_temp, _max_temp, _tolerance); } } void ZigbeeThermostat::setTemperatureReporting(uint16_t min_interval, uint16_t max_interval, float delta) { - /* Send "configure report attribute" command to the bound sensor */ - esp_zb_zcl_config_report_cmd_t report_cmd; + /* Send "configure report attribute" command to all bound sensors */ + esp_zb_zcl_config_report_cmd_t report_cmd = {0}; report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; report_cmd.zcl_basic_cmd.src_endpoint = _endpoint; report_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; @@ -206,10 +364,10 @@ void ZigbeeThermostat::setTemperatureReporting(uint16_t min_interval, uint16_t m .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16, .min_interval = min_interval, .max_interval = max_interval, - .reportable_change = &report_change, + .reportable_change = (void *)&report_change, }, }; - report_cmd.record_number = ZB_ARRAY_LENTH(records); + report_cmd.record_number = ZB_ARRAY_LENGHT(records); report_cmd.record_field = records; log_i("Sending 'configure reporting' command"); @@ -218,4 +376,93 @@ void ZigbeeThermostat::setTemperatureReporting(uint16_t min_interval, uint16_t m esp_zb_lock_release(); } +void ZigbeeThermostat::setTemperatureReporting(uint16_t group_addr, uint16_t min_interval, uint16_t max_interval, float delta) { + /* Send "configure report attribute" command to the group */ + esp_zb_zcl_config_report_cmd_t report_cmd = {0}; + report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; + report_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_cmd.zcl_basic_cmd.dst_addr_u.addr_short = group_addr; + report_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + + int16_t report_change = (int16_t)delta * 100; + esp_zb_zcl_config_report_record_t records[] = { + { + .direction = ESP_ZB_ZCL_REPORT_DIRECTION_SEND, + .attributeID = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, + .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16, + .min_interval = min_interval, + .max_interval = max_interval, + .reportable_change = (void *)&report_change, + }, + }; + report_cmd.record_number = ZB_ARRAY_LENGHT(records); + report_cmd.record_field = records; + + log_i("Sending 'configure reporting' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_config_report_cmd_req(&report_cmd); + esp_zb_lock_release(); +} + +void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, uint16_t short_addr, uint16_t min_interval, uint16_t max_interval, float delta) { + /* Send "configure report attribute" command to specific endpoint */ + esp_zb_zcl_config_report_cmd_t report_cmd = {0}; + report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + report_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_cmd.zcl_basic_cmd.dst_endpoint = endpoint; + report_cmd.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + report_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + + int16_t report_change = (int16_t)delta * 100; + esp_zb_zcl_config_report_record_t records[] = { + { + .direction = ESP_ZB_ZCL_REPORT_DIRECTION_SEND, + .attributeID = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, + .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16, + .min_interval = min_interval, + .max_interval = max_interval, + .reportable_change = (void *)&report_change, + }, + }; + report_cmd.record_number = ZB_ARRAY_LENGHT(records); + report_cmd.record_field = records; + + log_i("Sending 'configure reporting' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_config_report_cmd_req(&report_cmd); + esp_zb_lock_release(); +} + +void ZigbeeThermostat::setTemperatureReporting(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr, uint16_t min_interval, uint16_t max_interval, float delta) { + /* Send "configure report attribute" command to specific endpoint */ + esp_zb_zcl_config_report_cmd_t report_cmd = {0}; + report_cmd.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + report_cmd.zcl_basic_cmd.src_endpoint = _endpoint; + report_cmd.zcl_basic_cmd.dst_endpoint = endpoint; + report_cmd.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT; + memcpy(report_cmd.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + + int16_t report_change = (int16_t)delta * 100; + esp_zb_zcl_config_report_record_t records[] = { + { + .direction = ESP_ZB_ZCL_REPORT_DIRECTION_SEND, + .attributeID = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, + .attrType = ESP_ZB_ZCL_ATTR_TYPE_S16, + .min_interval = min_interval, + .max_interval = max_interval, + .reportable_change = (void *)&report_change, + }, + }; + report_cmd.record_number = ZB_ARRAY_LENGHT(records); + report_cmd.record_field = records; + + log_i( + "Sending 'configure reporting' command to endpoint %d, ieee address %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", endpoint, ieee_addr[7], ieee_addr[6], + ieee_addr[5], ieee_addr[4], ieee_addr[3], ieee_addr[2], ieee_addr[1], ieee_addr[0] + ); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_config_report_cmd_req(&report_cmd); + esp_zb_lock_release(); +} + #endif // CONFIG_ZB_ENABLED diff --git a/libraries/Zigbee/src/ep/ZigbeeThermostat.h b/libraries/Zigbee/src/ep/ZigbeeThermostat.h index acdcd68e512..c10a9d7f974 100644 --- a/libraries/Zigbee/src/ep/ZigbeeThermostat.h +++ b/libraries/Zigbee/src/ep/ZigbeeThermostat.h @@ -34,24 +34,39 @@ class ZigbeeThermostat : public ZigbeeEP { ZigbeeThermostat(uint8_t endpoint); ~ZigbeeThermostat() {} - void onTempRecieve(void (*callback)(float)) { - _on_temp_recieve = callback; + void onTempReceive(void (*callback)(float)) { + _on_temp_receive = callback; } - void onConfigRecieve(void (*callback)(float, float, float)) { - _on_config_recieve = callback; + void onTempReceiveWithSource(void (*callback)(float, uint8_t, esp_zb_zcl_addr_t)) { + _on_temp_receive_with_source = callback; + } + void onConfigReceive(void (*callback)(float, float, float)) { + _on_config_receive = callback; } void getTemperature(); + void getTemperature(uint16_t group_addr); + void getTemperature(uint8_t endpoint, uint16_t short_addr); + void getTemperature(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + void getSensorSettings(); + void getSensorSettings(uint16_t group_addr); + void getSensorSettings(uint8_t endpoint, uint16_t short_addr); + void getSensorSettings(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); + void setTemperatureReporting(uint16_t min_interval, uint16_t max_interval, float delta); + void setTemperatureReporting(uint16_t group_addr, uint16_t min_interval, uint16_t max_interval, float delta); + void setTemperatureReporting(uint8_t endpoint, uint16_t short_addr, uint16_t min_interval, uint16_t max_interval, float delta); + void setTemperatureReporting(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr, uint16_t min_interval, uint16_t max_interval, float delta); private: // save instance of the class in order to use it in static functions static ZigbeeThermostat *_instance; zb_device_params_t *_device; - void (*_on_temp_recieve)(float); - void (*_on_config_recieve)(float, float, float); + void (*_on_temp_receive)(float); + void (*_on_temp_receive_with_source)(float, uint8_t, esp_zb_zcl_addr_t); + void (*_on_config_receive)(float, float, float); float _min_temp; float _max_temp; float _tolerance; @@ -62,7 +77,7 @@ class ZigbeeThermostat : public ZigbeeEP { static void bindCbWrapper(esp_zb_zdp_status_t zdo_status, void *user_ctx); static void findCbWrapper(esp_zb_zdp_status_t zdo_status, uint16_t addr, uint8_t endpoint, void *user_ctx); - void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute) override; + void zbAttributeRead(uint16_t cluster_id, const esp_zb_zcl_attribute_t *attribute, uint8_t src_endpoint, esp_zb_zcl_addr_t src_address) override; }; #endif // CONFIG_ZB_ENABLED