diff --git a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino index 00e3cd170ef..15e120a1dbd 100644 --- a/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_Color_Dimmer_Switch/Zigbee_Color_Dimmer_Switch.ino @@ -145,6 +145,6 @@ void loop() { static uint32_t last_print = 0; if (millis() - last_print > 30000) { last_print = millis(); - zbSwitch.printBoundDevices(); + zbSwitch.printBoundDevices(Serial); } } diff --git a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino index e38734a052a..e12b8aaf9ea 100644 --- a/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino +++ b/libraries/Zigbee/examples/Zigbee_On_Off_Switch/Zigbee_On_Off_Switch.ino @@ -138,17 +138,16 @@ void setup() { delay(500); } - // Optional: read manufacturer and model name from the bound light + // Optional: List all bound devices and read manufacturer and model name std::list boundLights = zbSwitch.getBoundDevices(); - //List all bound lights for (const auto &device : boundLights) { - Serial.printf("Device on endpoint %d, short address: 0x%x\n", device->endpoint, device->short_addr); + Serial.printf("Device on endpoint %d, short address: 0x%x\r\n", device->endpoint, device->short_addr); Serial.printf( - "IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", device->ieee_addr[0], device->ieee_addr[1], device->ieee_addr[2], device->ieee_addr[3], - device->ieee_addr[4], device->ieee_addr[5], device->ieee_addr[6], device->ieee_addr[7] + "IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\r\n", 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] ); - Serial.printf("Light manufacturer: %s", zbSwitch.readManufacturer(device->endpoint, device->short_addr)); - Serial.printf("Light model: %s", zbSwitch.readModel(device->endpoint, device->short_addr)); + Serial.printf("Light manufacturer: %s\r\n", zbSwitch.readManufacturer(device->endpoint, device->short_addr, device->ieee_addr)); + Serial.printf("Light model: %s\r\n", zbSwitch.readModel(device->endpoint, device->short_addr, device->ieee_addr)); } Serial.println(); @@ -191,6 +190,6 @@ void loop() { static uint32_t lastPrint = 0; if (millis() - lastPrint > 10000) { lastPrint = millis(); - zbSwitch.printBoundDevices(); + zbSwitch.printBoundDevices(Serial); } } diff --git a/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino index e13e6a877a6..0c2f9b56690 100644 --- a/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino +++ b/libraries/Zigbee/examples/Zigbee_Temp_Hum_Sensor_Sleepy/Zigbee_Temp_Hum_Sensor_Sleepy.ino @@ -128,6 +128,7 @@ void loop() { // If key pressed for more than 3secs, factory reset Zigbee and reboot Serial.println("Resetting Zigbee to factory and rebooting in 1s."); delay(1000); + Zigbee.factoryReset(); } } } diff --git a/libraries/Zigbee/src/ZigbeeCore.cpp b/libraries/Zigbee/src/ZigbeeCore.cpp index 442dc4b7ee0..b1dc6211362 100644 --- a/libraries/Zigbee/src/ZigbeeCore.cpp +++ b/libraries/Zigbee/src/ZigbeeCore.cpp @@ -243,6 +243,7 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } else { Zigbee._connected = true; } + Zigbee.searchBindings(); } } else { /* commissioning failed */ @@ -309,7 +310,6 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { Bit 6 – Security capability Bit 7 – Reserved */ - // for each endpoint in the list call the findEndpoint function if not bounded or allowed to bind multiple devices for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { if (!(*it)->bound() || (*it)->epAllowMultipleBinding()) { @@ -329,6 +329,12 @@ void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { } } break; + case ESP_ZB_ZDO_SIGNAL_LEAVE: // End Device + Router + // Device was removed from the network, factory reset the device + if ((zigbee_role_t)Zigbee.getRole() != ZIGBEE_COORDINATOR) { + Zigbee.factoryReset(); + } + break; default: log_v("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, esp_err_to_name(err_status)); break; } } @@ -391,6 +397,75 @@ void ZigbeeCore::scanDelete() { _scan_status = ZB_SCAN_FAILED; } +// Recall bounded devices from the binding table after reboot +void ZigbeeCore::bindingTableCb(const esp_zb_zdo_binding_table_info_t *table_info, void *user_ctx) { + bool done = true; + esp_zb_zdo_mgmt_bind_param_t *req = (esp_zb_zdo_mgmt_bind_param_t *)user_ctx; + esp_zb_zdp_status_t zdo_status = (esp_zb_zdp_status_t)table_info->status; + log_d("Binding table callback for address 0x%04x with status %d", req->dst_addr, zdo_status); + if (zdo_status == ESP_ZB_ZDP_STATUS_SUCCESS) { + // Print binding table log simple + log_d("Binding table info: total %d, index %d, count %d", table_info->total, table_info->index, table_info->count); + + if (table_info->total == 0) { + log_d("No binding table entries found"); + free(req); + return; + } + + esp_zb_zdo_binding_table_record_t *record = table_info->record; + for (int i = 0; i < table_info->count; i++) { + log_d( + "Binding table record: src_endp %d, dst_endp %d, cluster_id 0x%04x, dst_addr_mode %d", record->src_endp, record->dst_endp, record->cluster_id, + record->dst_addr_mode + ); + + zb_device_params_t *device = (zb_device_params_t *)calloc(1, sizeof(zb_device_params_t)); + device->endpoint = record->dst_endp; + if (record->dst_addr_mode == ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT || record->dst_addr_mode == ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT) { + device->short_addr = record->dst_address.addr_short; + } else { //ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT + memcpy(device->ieee_addr, record->dst_address.addr_long, sizeof(esp_zb_ieee_addr_t)); + } + + // Add to list of bound devices of proper endpoint + for (std::list::iterator it = Zigbee.ep_objects.begin(); it != Zigbee.ep_objects.end(); ++it) { + if ((*it)->getEndpoint() == record->src_endp) { + (*it)->addBoundDevice(device); + log_d( + "Device bound to EP %d -> device endpoint: %d, short addr: 0x%04x, ieee addr: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", record->src_endp, + device->endpoint, device->short_addr, 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] + ); + } + } + record = record->next; + } + + // Continue reading the binding table + if (table_info->index + table_info->count < table_info->total) { + /* There are unreported binding table entries, request for them. */ + req->start_index = table_info->index + table_info->count; + esp_zb_zdo_binding_table_req(req, bindingTableCb, req); + done = false; + } + } + + if (done) { + // Print bound devices + log_d("Filling bounded devices finished"); + free(req); + } +} + +void ZigbeeCore::searchBindings() { + esp_zb_zdo_mgmt_bind_param_t *mb_req = (esp_zb_zdo_mgmt_bind_param_t *)malloc(sizeof(esp_zb_zdo_mgmt_bind_param_t)); + mb_req->dst_addr = esp_zb_get_short_address(); + mb_req->start_index = 0; + log_d("Requesting binding table for address 0x%04x", mb_req->dst_addr); + esp_zb_zdo_binding_table_req(mb_req, bindingTableCb, (void *)mb_req); +} + // Function to convert enum value to string const char *ZigbeeCore::getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId) { switch (deviceId) { diff --git a/libraries/Zigbee/src/ZigbeeCore.h b/libraries/Zigbee/src/ZigbeeCore.h index 75fecd59198..6729b7cc9f4 100644 --- a/libraries/Zigbee/src/ZigbeeCore.h +++ b/libraries/Zigbee/src/ZigbeeCore.h @@ -80,6 +80,8 @@ class ZigbeeCore { bool zigbeeInit(esp_zb_cfg_t *zb_cfg, bool erase_nvs); static void scanCompleteCallback(esp_zb_zdp_status_t zdo_status, uint8_t count, esp_zb_network_descriptor_t *nwk_descriptor); const char *getDeviceTypeString(esp_zb_ha_standard_devices_t deviceId); + void searchBindings(); + static void bindingTableCb(const esp_zb_zdo_binding_table_info_t *table_info, void *user_ctx); public: ZigbeeCore(); diff --git a/libraries/Zigbee/src/ZigbeeEP.cpp b/libraries/Zigbee/src/ZigbeeEP.cpp index 0a947d3ab9e..dbfe8596268 100644 --- a/libraries/Zigbee/src/ZigbeeEP.cpp +++ b/libraries/Zigbee/src/ZigbeeEP.cpp @@ -7,6 +7,8 @@ #include "esp_zigbee_cluster.h" #include "zcl/esp_zigbee_zcl_power_config.h" +#define ZB_CMD_TIMEOUT 10000 // 10 seconds + bool ZigbeeEP::_is_bound = false; bool ZigbeeEP::_allow_multiple_binding = false; @@ -112,13 +114,20 @@ void ZigbeeEP::reportBatteryPercentage() { log_v("Battery percentage reported"); } -char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr) { +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; - read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + + if (short_addr != 0) { + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + } else { + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + } + 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_BASIC; uint16_t attributes[] = { @@ -130,22 +139,31 @@ char *ZigbeeEP::readManufacturer(uint8_t endpoint, uint16_t short_addr) { // clear read manufacturer _read_manufacturer = nullptr; + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); //Wait for response or timeout - if (xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE) { + if (xSemaphoreTake(lock, ZB_CMD_TIMEOUT) != pdTRUE) { log_e("Error while reading manufacturer"); } return _read_manufacturer; } -char *ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr) { +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; - read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + + if (short_addr != 0) { + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; + read_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; + } else { + read_req.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT; + memcpy(read_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + } + 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_BASIC; uint16_t attributes[] = { @@ -157,11 +175,12 @@ char *ZigbeeEP::readModel(uint8_t endpoint, uint16_t short_addr) { // clear read model _read_model = nullptr; + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_read_attr_cmd_req(&read_req); + esp_zb_lock_release(); //Wait for response or timeout - //Semaphore take - if (xSemaphoreTake(lock, portMAX_DELAY) != pdTRUE) { + if (xSemaphoreTake(lock, ZB_CMD_TIMEOUT) != pdTRUE) { log_e("Error while reading model"); } return _read_model; @@ -171,8 +190,23 @@ void ZigbeeEP::printBoundDevices() { log_i("Bound devices:"); for ([[maybe_unused]] const auto &device : _bound_devices) { - log_i("Device on endpoint %d, short address: 0x%x", device->endpoint, device->short_addr); - print_ieee_addr(device->ieee_addr); + log_i( + "Device on endpoint %d, short address: 0x%x, ieee address: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x", device->endpoint, device->short_addr, + 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] + ); + } +} + +void ZigbeeEP::printBoundDevices(Print &print) { + print.println("Bound devices:"); + for ([[maybe_unused]] + const auto &device : _bound_devices) { + print.printf( + "Device on endpoint %d, short address: 0x%x, ieee address: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\r\n", device->endpoint, device->short_addr, + 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] + ); } } diff --git a/libraries/Zigbee/src/ZigbeeEP.h b/libraries/Zigbee/src/ZigbeeEP.h index 21ed7706d31..522c84620ff 100644 --- a/libraries/Zigbee/src/ZigbeeEP.h +++ b/libraries/Zigbee/src/ZigbeeEP.h @@ -9,8 +9,6 @@ /* Useful defines */ #define ZB_ARRAY_LENTH(arr) (sizeof(arr) / sizeof(arr[0])) -#define print_ieee_addr(addr) \ - log_i("IEEE Address: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]) #define XYZ_TO_RGB(X, Y, Z, r, g, b) \ { \ r = (float)(3.240479 * (X) - 1.537150 * (Y) - 0.498535 * (Z)); \ @@ -69,6 +67,8 @@ class ZigbeeEP { } void printBoundDevices(); + void printBoundDevices(Print &print); + std::list getBoundDevices() const { return _bound_devices; } @@ -87,8 +87,8 @@ class ZigbeeEP { void reportBatteryPercentage(); // Methods to read manufacturer and model name from selected endpoint and short address - char *readManufacturer(uint8_t endpoint, uint16_t short_addr); - char *readModel(uint8_t endpoint, uint16_t short_addr); + char *readManufacturer(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr); + char *readModel(uint8_t endpoint, uint16_t short_addr, esp_zb_ieee_addr_t ieee_addr); bool epAllowMultipleBinding() { return _allow_multiple_binding; @@ -108,7 +108,6 @@ class ZigbeeEP { } private: - static bool _allow_multiple_binding; char *_read_manufacturer; char *_read_model; void (*_on_identify)(uint16_t time); @@ -119,10 +118,15 @@ class ZigbeeEP { esp_zb_endpoint_config_t _ep_config; esp_zb_cluster_list_t *_cluster_list; static bool _is_bound; + static bool _allow_multiple_binding; std::list _bound_devices; SemaphoreHandle_t lock; zb_power_source_t _power_source; + void addBoundDevice(zb_device_params_t *device) { + _bound_devices.push_back(device); + _is_bound = true; + } friend class ZigbeeCore; }; diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp index 8e72728f6a2..4fd492a5477 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.cpp @@ -98,10 +98,10 @@ void ZigbeeColorDimmerSwitch::lightToggle() { 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; - log_i("Sending 'light toggle' command"); - //esp_zb_lock_acquire(portMAX_DELAY); + log_v("Sending 'light toggle' command"); + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_cmd_req(&cmd_req); - //esp_zb_lock_release(); + esp_zb_lock_release(); } else { log_e("Light not bound"); } @@ -114,7 +114,7 @@ void ZigbeeColorDimmerSwitch::lightToggle(uint16_t group_addr) { 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; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; - log_i("Sending 'light toggle' command to group address 0x%x", group_addr); + log_v("Sending 'light toggle' command to group address 0x%x", group_addr); esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -131,7 +131,27 @@ void ZigbeeColorDimmerSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; - log_i("Sending 'light toggle' command to endpoint %d, address 0x%x", endpoint, short_addr); + log_v("Sending 'light toggle' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +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; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + log_v( + "Sending 'light toggle' 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_on_off_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -146,7 +166,7 @@ void ZigbeeColorDimmerSwitch::lightOn() { 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; - log_i("Sending 'light on' command"); + log_v("Sending 'light on' command"); esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -162,7 +182,7 @@ void ZigbeeColorDimmerSwitch::lightOn(uint16_t group_addr) { 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; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; - log_i("Sending 'light on' command to group address 0x%x", group_addr); + log_v("Sending 'light on' command to group address 0x%x", group_addr); esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -179,7 +199,27 @@ void ZigbeeColorDimmerSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; - log_i("Sending 'light on' command to endpoint %d, address 0x%x", endpoint, short_addr); + log_v("Sending 'light on' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +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; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + log_v( + "Sending 'light on' 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_on_off_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -194,7 +234,7 @@ void ZigbeeColorDimmerSwitch::lightOff() { 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; - log_i("Sending 'light off' command"); + log_v("Sending 'light off' command"); esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -210,7 +250,7 @@ void ZigbeeColorDimmerSwitch::lightOff(uint16_t group_addr) { 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; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; - log_i("Sending 'light off' command to group address 0x%x", group_addr); + log_v("Sending 'light off' command to group address 0x%x", group_addr); esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -227,7 +267,27 @@ void ZigbeeColorDimmerSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; - log_i("Sending 'light off' command to endpoint %d, address 0x%x", endpoint, short_addr); + log_v("Sending 'light off' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +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; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + log_v( + "Sending 'light off' 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_on_off_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -243,7 +303,7 @@ void ZigbeeColorDimmerSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effe cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.effect_id = effect_id; cmd_req.effect_variant = effect_variant; - log_i("Sending 'light off with effect' command"); + log_v("Sending 'light off with effect' command"); esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_off_with_effect_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -257,7 +317,7 @@ void ZigbeeColorDimmerSwitch::lightOnWithSceneRecall() { esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; - log_i("Sending 'light on with scene recall' command"); + log_v("Sending 'light on with scene recall' command"); esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -274,7 +334,7 @@ void ZigbeeColorDimmerSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16 cmd_req.on_off_control = on_off_control; //TODO: Test how it works, then maybe change API cmd_req.on_time = time_on; cmd_req.off_wait_time = time_off; - log_i("Sending 'light on with time off' command"); + log_v("Sending 'light on with time off' command"); esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_on_with_timed_off_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -290,7 +350,7 @@ void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level) { cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.level = level; cmd_req.transition_time = 0xffff; - log_i("Sending 'set light level' command"); + log_v("Sending 'set light level' command"); esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -307,7 +367,7 @@ void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint16_t group_addr) cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT; cmd_req.level = level; cmd_req.transition_time = 0xffff; - log_i("Sending 'set light level' command to group address 0x%x", group_addr); + log_v("Sending 'set light level' command to group address 0x%x", group_addr); esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -325,7 +385,28 @@ void ZigbeeColorDimmerSwitch::setLightLevel(uint8_t level, uint8_t endpoint, uin cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; cmd_req.level = level; cmd_req.transition_time = 0xffff; - log_i("Sending 'set light level' command to endpoint %d, address 0x%x", endpoint, short_addr); + log_v("Sending 'set light level' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_level_move_to_level_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +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; + 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; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + cmd_req.level = level; + cmd_req.transition_time = 0xffff; + log_v( + "Sending 'set light level' 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_level_move_to_level_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -346,7 +427,7 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t cmd_req.color_x = color_x; cmd_req.color_y = color_y; cmd_req.transition_time = 0; - log_i("Sending 'set light color' command"); + log_v("Sending 'set light color' command"); esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -368,7 +449,7 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t cmd_req.color_x = color_x; cmd_req.color_y = color_y; cmd_req.transition_time = 0; - log_i("Sending 'set light color' command to group address 0x%x", group_addr); + log_v("Sending 'set light color' command to group address 0x%x", group_addr); esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); esp_zb_lock_release(); @@ -391,7 +472,33 @@ void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t cmd_req.color_x = color_x; cmd_req.color_y = color_y; cmd_req.transition_time = 0; - log_i("Sending 'set light color' command to endpoint %d, address 0x%x", endpoint, short_addr); + log_v("Sending 'set light color' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_color_move_to_color_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +void ZigbeeColorDimmerSwitch::setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr) { + if (_is_bound) { + //Convert RGB to XY + uint16_t color_x, color_y; + calculateXY(red, green, blue, color_x, color_y); + + esp_zb_zcl_color_move_to_color_cmd_t cmd_req; + 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; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + cmd_req.color_x = color_x; + cmd_req.color_y = color_y; + cmd_req.transition_time = 0; + log_v( + "Sending 'set light color' 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_color_move_to_color_cmd_req(&cmd_req); esp_zb_lock_release(); diff --git a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h index 9b623d2f8ef..8e2a4d9e1a3 100644 --- a/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h +++ b/libraries/Zigbee/src/ep/ZigbeeColorDimmerSwitch.h @@ -18,14 +18,17 @@ class ZigbeeColorDimmerSwitch : public ZigbeeEP { void lightToggle(); void lightToggle(uint16_t group_addr); void lightToggle(uint8_t endpoint, uint16_t short_addr); + void lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); void lightOn(); void lightOn(uint16_t group_addr); void lightOn(uint8_t endpoint, uint16_t short_addr); + void lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); void lightOff(); void lightOff(uint16_t group_addr); void lightOff(uint8_t endpoint, uint16_t short_addr); + void lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); void lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant); void lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off); @@ -34,10 +37,12 @@ class ZigbeeColorDimmerSwitch : public ZigbeeEP { void setLightLevel(uint8_t level); void setLightLevel(uint8_t level, uint16_t group_addr); void setLightLevel(uint8_t level, uint8_t endpoint, uint16_t short_addr); + void setLightLevel(uint8_t level, uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); void setLightColor(uint8_t red, uint8_t green, uint8_t blue); void setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint16_t group_addr); void setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t endpoint, uint16_t short_addr); + void setLightColor(uint8_t red, uint8_t green, uint8_t blue, uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); private: // save instance of the class in order to use it in static functions diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp index 16af8008a8a..f6b36d7f0d4 100644 --- a/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.cpp @@ -59,7 +59,6 @@ void ZigbeeSwitch::findEndpoint(esp_zb_zdo_match_desc_req_param_t *cmd_req) { .num_out_clusters = 1, .cluster_list = cluster_list, }; - esp_zb_zdo_match_cluster(&on_off_req, findCb, &_endpoint); } @@ -70,8 +69,10 @@ void ZigbeeSwitch::lightToggle() { 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; - log_i("Sending 'light toggle' command"); + log_v("Sending 'light toggle' command"); + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); } else { log_e("Light not bound"); } @@ -84,8 +85,10 @@ void ZigbeeSwitch::lightToggle(uint16_t group_addr) { 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; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; - log_i("Sending 'light toggle' command to group address 0x%x", group_addr); + log_v("Sending 'light toggle' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); } else { log_e("Light not bound"); } @@ -99,8 +102,30 @@ void ZigbeeSwitch::lightToggle(uint8_t endpoint, uint16_t short_addr) { cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; - log_i("Sending 'light toggle' command to endpoint %d, address 0x%x", endpoint, short_addr); + log_v("Sending 'light toggle' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +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; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_TOGGLE_ID; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + log_v( + "Sending 'light toggle' 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_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); } else { log_e("Light not bound"); } @@ -112,8 +137,10 @@ void ZigbeeSwitch::lightOn() { 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; - log_i("Sending 'light on' command"); + log_v("Sending 'light on' command"); + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); } else { log_e("Light not bound"); } @@ -126,8 +153,10 @@ void ZigbeeSwitch::lightOn(uint16_t group_addr) { 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; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; - log_i("Sending 'light on' command to group address 0x%x", group_addr); + log_v("Sending 'light on' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); } else { log_e("Light not bound"); } @@ -141,8 +170,30 @@ void ZigbeeSwitch::lightOn(uint8_t endpoint, uint16_t short_addr) { cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; - log_i("Sending 'light on' command to endpoint %d, address 0x%x", endpoint, short_addr); + log_v("Sending 'light on' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +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; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_ON_ID; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + log_v( + "Sending 'light on' 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_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); } else { log_e("Light not bound"); } @@ -154,8 +205,10 @@ void ZigbeeSwitch::lightOff() { 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; - log_i("Sending 'light off' command"); + log_v("Sending 'light off' command"); + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); } else { log_e("Light not bound"); } @@ -168,8 +221,10 @@ void ZigbeeSwitch::lightOff(uint16_t group_addr) { 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; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; - log_i("Sending 'light off' command to group address 0x%x", group_addr); + log_v("Sending 'light off' command to group address 0x%x", group_addr); + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); } else { log_e("Light not bound"); } @@ -183,8 +238,30 @@ void ZigbeeSwitch::lightOff(uint8_t endpoint, uint16_t short_addr) { cmd_req.zcl_basic_cmd.dst_addr_u.addr_short = short_addr; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT; cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; - log_i("Sending 'light off' command to endpoint %d, address 0x%x", endpoint, short_addr); + log_v("Sending 'light off' command to endpoint %d, address 0x%x", endpoint, short_addr); + esp_zb_lock_acquire(portMAX_DELAY); + esp_zb_zcl_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); + } else { + log_e("Light not bound"); + } +} + +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; + 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; + cmd_req.on_off_cmd_id = ESP_ZB_ZCL_CMD_ON_OFF_OFF_ID; + memcpy(cmd_req.zcl_basic_cmd.dst_addr_u.addr_long, ieee_addr, sizeof(esp_zb_ieee_addr_t)); + log_v( + "Sending 'light off' 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_on_off_cmd_req(&cmd_req); + esp_zb_lock_release(); } else { log_e("Light not bound"); } @@ -197,8 +274,10 @@ void ZigbeeSwitch::lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant) cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; cmd_req.effect_id = effect_id; cmd_req.effect_variant = effect_variant; - log_i("Sending 'light off with effect' command"); + log_v("Sending 'light off with effect' command"); + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_off_with_effect_cmd_req(&cmd_req); + esp_zb_lock_release(); } else { log_e("Light not bound"); } @@ -209,8 +288,10 @@ void ZigbeeSwitch::lightOnWithSceneRecall() { esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_t cmd_req; cmd_req.zcl_basic_cmd.src_endpoint = _endpoint; cmd_req.address_mode = ESP_ZB_APS_ADDR_MODE_DST_ADDR_ENDP_NOT_PRESENT; - log_i("Sending 'light on with scene recall' command"); + log_v("Sending 'light on with scene recall' command"); + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_on_with_recall_global_scene_cmd_req(&cmd_req); + esp_zb_lock_release(); } else { log_e("Light not bound"); } @@ -223,8 +304,10 @@ void ZigbeeSwitch::lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, cmd_req.on_off_control = on_off_control; //TODO: Test how it works, then maybe change API cmd_req.on_time = time_on; cmd_req.off_wait_time = time_off; - log_i("Sending 'light on with time off' command"); + log_v("Sending 'light on with time off' command"); + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_on_off_on_with_timed_off_cmd_req(&cmd_req); + esp_zb_lock_release(); } else { log_e("Light not bound"); } diff --git a/libraries/Zigbee/src/ep/ZigbeeSwitch.h b/libraries/Zigbee/src/ep/ZigbeeSwitch.h index a8d892f37e9..62264641378 100644 --- a/libraries/Zigbee/src/ep/ZigbeeSwitch.h +++ b/libraries/Zigbee/src/ep/ZigbeeSwitch.h @@ -18,14 +18,17 @@ class ZigbeeSwitch : public ZigbeeEP { void lightToggle(); void lightToggle(uint16_t group_addr); void lightToggle(uint8_t endpoint, uint16_t short_addr); + void lightToggle(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); void lightOn(); void lightOn(uint16_t group_addr); void lightOn(uint8_t endpoint, uint16_t short_addr); + void lightOn(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); void lightOff(); void lightOff(uint16_t group_addr); void lightOff(uint8_t endpoint, uint16_t short_addr); + void lightOff(uint8_t endpoint, esp_zb_ieee_addr_t ieee_addr); void lightOffWithEffect(uint8_t effect_id, uint8_t effect_variant); void lightOnWithTimedOff(uint8_t on_off_control, uint16_t time_on, uint16_t time_off); diff --git a/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp index 718c892f638..3dfac0489dd 100644 --- a/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp +++ b/libraries/Zigbee/src/ep/ZigbeeTempSensor.cpp @@ -60,7 +60,9 @@ void ZigbeeTempSensor::setReporting(uint16_t min_interval, uint16_t max_interval }, .manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC, }; + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_update_reporting_info(&reporting_info); + esp_zb_lock_release(); } void ZigbeeTempSensor::setTemperature(float temperature) { @@ -158,7 +160,9 @@ void ZigbeeTempSensor::setHumidityReporting(uint16_t min_interval, uint16_t max_ }, .manuf_code = ESP_ZB_ZCL_ATTR_NON_MANUFACTURER_SPECIFIC, }; + esp_zb_lock_acquire(portMAX_DELAY); esp_zb_zcl_update_reporting_info(&reporting_info); + esp_zb_lock_release(); } #endif //SOC_IEEE802154_SUPPORTED && CONFIG_ZB_ENABLED