Created
March 18, 2023 17:28
-
-
Save varofla/308c47c9a7d9b650170398a196527641 to your computer and use it in GitHub Desktop.
ESP-Zigbee-SDK의 HA_on_off_light 예제를 Home Assistant에 사용할 수 있도록 수정
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD | |
* | |
* SPDX-License-Identifier: LicenseRef-Included | |
* | |
* Redistribution and use in source and binary forms, with or without modification, | |
* are permitted provided that the following conditions are met: | |
* | |
* 1. Redistributions of source code must retain the above copyright notice, | |
* this list of conditions and the following disclaimer. | |
* | |
* 2. Redistributions in binary form, except as embedded into a Espressif Systems | |
* integrated circuit in a product or a software update for such product, | |
* must reproduce the above copyright notice, this list of conditions and | |
* the following disclaimer in the documentation and/or other materials | |
* provided with the distribution. | |
* | |
* 3. Neither the name of the copyright holder nor the names of its contributors | |
* may be used to endorse or promote products derived from this software without | |
* specific prior written permission. | |
* | |
* 4. Any software provided in binary form under this license must not be reverse | |
* engineered, decompiled, modified and/or disassembled. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
* POSSIBILITY OF SUCH DAMAGE. | |
*/ | |
#include <malloc.h> | |
#include <string.h> | |
#include "esp_log.h" | |
#include "esp_zb_light.h" | |
#include "freertos/FreeRTOS.h" | |
#include "freertos/task.h" | |
#include "ha/esp_zigbee_ha_standard.h" | |
#include "nvs_flash.h" | |
#define ZCL_BASIC_POWER_SOURCE 0x04 | |
#define ZCL_BASIC_MODEL_IDENTIFIER "ESP32C6_TestLight" | |
#define ZCL_BASIC_MANUFACTURER_NAME "Espressif" | |
/** | |
* @note Make sure set idf.py menuconfig in zigbee component as zigbee end device! | |
*/ | |
#if !defined ZB_ED_ROLE | |
#error Define ZB_ED_ROLE in idf.py menuconfig to compile light (End Device) source code. | |
#endif | |
static const char *TAG = "ESP_ZB_ON_OFF_LIGHT"; | |
/********************* Define functions **************************/ | |
static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) { | |
ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); | |
} | |
void attr_cb(uint8_t status, uint8_t endpoint, uint16_t cluster_id, uint16_t attr_id, void *new_value) { | |
if (cluster_id == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { | |
uint8_t value = *(uint8_t *)new_value; | |
if (attr_id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID) { | |
/* implemented light on/off control */ | |
ESP_LOGI(TAG, "on/off light set to %hd", value); | |
light_driver_set_power((bool)value); | |
} | |
} else { | |
/* Implement some actions if needed when other cluster changed */ | |
ESP_LOGI(TAG, "cluster:0x%x, attribute:0x%x changed ", cluster_id, attr_id); | |
} | |
} | |
void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) { | |
uint32_t *p_sg_p = signal_struct->p_app_signal; | |
esp_err_t err_status = signal_struct->esp_err_status; | |
esp_zb_app_signal_type_t sig_type = *p_sg_p; | |
switch (sig_type) { | |
case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: | |
ESP_LOGI(TAG, "Zigbee stack initialized"); | |
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); | |
break; | |
case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: | |
case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: | |
if (err_status == ESP_OK) { | |
ESP_LOGI(TAG, "Start network steering"); | |
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); | |
} else { | |
ESP_LOGE(TAG, "Failed to initialize Zigbee stack (status: %d)", err_status); | |
} | |
break; | |
case ESP_ZB_BDB_SIGNAL_STEERING: | |
if (err_status == ESP_OK) { | |
esp_zb_ieee_addr_t extended_pan_id; | |
esp_zb_get_extended_pan_id(extended_pan_id); | |
ESP_LOGI(TAG, "Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx)", | |
extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], | |
extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], extended_pan_id[0], | |
esp_zb_get_pan_id()); | |
} else { | |
ESP_LOGI(TAG, "Network steering was not successful (status: %d)", err_status); | |
esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000); | |
} | |
break; | |
default: | |
ESP_LOGI(TAG, "ZDO signal: %d, status: %d", sig_type, err_status); | |
break; | |
} | |
} | |
static char *s_string_to_zcl_string(char *str) { | |
int len = strlen(str); | |
char *arr = (char *)malloc((len + 1) * sizeof(char)); | |
if (arr == NULL) { | |
ESP_LOGE("s_string_to_zcl_string", "memory allocation failed!!"); | |
return NULL; | |
} | |
*arr = len; | |
strcpy(arr + 1, str); | |
return arr; | |
} | |
static void esp_zb_task(void *pvParameters) { | |
/* initialize Zigbee stack with Zigbee end-device config */ | |
esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZED_CONFIG(); | |
esp_zb_init(&zb_nwk_cfg); | |
esp_zb_set_primary_network_channel_set(0x07FFF800); // 11~26 channel | |
/* basic cluster attribute list */ | |
void *free1, *free2; | |
esp_zb_attribute_list_t *esp_zb_basic_cluster = esp_zb_basic_cluster_create(NULL); | |
esp_zb_cluster_update_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID, &(uint8_t){ZCL_BASIC_POWER_SOURCE}); | |
esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, free1 = s_string_to_zcl_string(ZCL_BASIC_MODEL_IDENTIFIER)); | |
esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, free2 = s_string_to_zcl_string(ZCL_BASIC_MANUFACTURER_NAME)); | |
/* identify cluster attribute list */ | |
esp_zb_attribute_list_t *esp_zb_identify_cluster = esp_zb_identify_cluster_create(NULL); | |
/* group cluster attribute list */ | |
esp_zb_attribute_list_t *esp_zb_groups_cluster = esp_zb_groups_cluster_create(NULL); | |
/* scenes cluster attribute list */ | |
esp_zb_attribute_list_t *esp_zb_scenes_cluster = esp_zb_scenes_cluster_create(NULL); | |
/* on-off cluster attribute list */ | |
esp_zb_on_off_cluster_cfg_t on_off_cfg; | |
on_off_cfg.on_off = ESP_ZB_ZCL_ON_OFF_ON_OFF_DEFAULT_VALUE; | |
esp_zb_attribute_list_t *esp_zb_on_off_cluster = esp_zb_on_off_cluster_create(&on_off_cfg); | |
free(free1); | |
free(free2); | |
/* create cluster lists */ | |
esp_zb_cluster_list_t *esp_zb_cluster_list = esp_zb_zcl_cluster_list_create(); | |
esp_zb_cluster_list_add_basic_cluster(esp_zb_cluster_list, esp_zb_basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); | |
esp_zb_cluster_list_add_identify_cluster(esp_zb_cluster_list, esp_zb_identify_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); | |
esp_zb_cluster_list_add_groups_cluster(esp_zb_cluster_list, esp_zb_groups_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); | |
esp_zb_cluster_list_add_scenes_cluster(esp_zb_cluster_list, esp_zb_scenes_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); | |
esp_zb_cluster_list_add_on_off_cluster(esp_zb_cluster_list, esp_zb_on_off_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); | |
/* endpoint list */ | |
esp_zb_ep_list_t *esp_zb_ep_list = esp_zb_ep_list_create(); | |
esp_zb_ep_list_add_ep(esp_zb_ep_list, esp_zb_cluster_list, HA_ESP_LIGHT_ENDPOINT, ESP_ZB_AF_HA_PROFILE_ID, ESP_ZB_HA_ON_OFF_OUTPUT_DEVICE_ID); | |
esp_zb_device_register(esp_zb_ep_list); | |
esp_zb_device_add_set_attr_value_cb(attr_cb); | |
ESP_ERROR_CHECK(esp_zb_start(false)); | |
esp_zb_main_loop_iteration(); | |
} | |
void app_main(void) { | |
esp_zb_platform_config_t config = { | |
.radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(), | |
.host_config = ESP_ZB_DEFAULT_HOST_CONFIG(), | |
}; | |
ESP_ERROR_CHECK(nvs_flash_init()); | |
/* load Zigbee light_bulb platform config to initialization */ | |
ESP_ERROR_CHECK(esp_zb_platform_config(&config)); | |
/* hardware related and device init */ | |
light_driver_init(LIGHT_DEFAULT_OFF); | |
xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
5초 간격으로 LED 토글하고, Z2M에 이를 전달하는 예제