diff --git a/CMakeLists.txt b/CMakeLists.txt index c39d01c..dbe9cb5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,5 @@ cmake_minimum_required(VERSION 3.16) set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/../esp-zigbee-sdk/components) include($ENV{IDF_PATH}/tools/cmake/project.cmake) -project(st7290) -idf_build_set_property(CXX_COMPILE_OPTIONS "-Wno-missing-field-initializers" APPEND) - +project(zigbee_light) +idf_build_set_property(CXX_COMPILE_OPTIONS "-Wno-missing-field-initializers" APPEND) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..fb6f2e3 --- /dev/null +++ b/README.md @@ -0,0 +1,13 @@ +# Zigbee lampka nad szafą + +Bo tasmota coś rwie, mam nadzieje ze to nie bedzie bo sie wkurwie + +Generalnie co ma dzialac to juz dziala, thank fuck. Ja pierdole ale api do zigbee jest pojebane + +### TODO + - hardware + - docyrklowac pwm: wyzsza rozdzielczosc, przeliczyc gamme na starcie (look up table na 254 wartosci, kazda wartosc to wyliczony PWM z gammom z powf, + minimalna jasnosc?) + - identyfikacja, niby opcjonalna ale fajny bajer + - factory reset zigbee zeby bylo legitnie, dzwonisz po `esp_zb_factory_reset();` + - status LED zeby bylo legitnie (pokazuje factory reset i OTA kiedys) + - ota? diff --git a/dependencies.lock b/dependencies.lock index 6ba4c05..bb850b1 100644 --- a/dependencies.lock +++ b/dependencies.lock @@ -6,8 +6,7 @@ dependencies: type: local version: 1.6.8 espressif/cmake_utilities: - component_hash: - 351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f + component_hash: 351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f dependencies: - name: idf require: private @@ -17,8 +16,7 @@ dependencies: type: service version: 0.5.3 espressif/esp-zboss-lib: - component_hash: - 321883d142421f65009972408287441794250057668a11abbdfd8bec77c3309a + component_hash: 321883d142421f65009972408287441794250057668a11abbdfd8bec77c3309a dependencies: - name: idf require: private @@ -27,17 +25,6 @@ dependencies: registry_url: https://components.espressif.com/ type: service version: 1.6.4 - espressif/led_strip: - component_hash: - 7e92a0c8a2e35b40904f88e88ce3c0dffff504a2763f70fba7ef4787cf2eec83 - dependencies: - - name: idf - require: private - version: '>=5.0' - source: - registry_url: https://components.espressif.com/ - type: service - version: 2.0.0 idf: source: type: idf @@ -46,8 +33,7 @@ direct_dependencies: - espressif/cmake_utilities - espressif/esp-zboss-lib - espressif/esp-zigbee-lib -- espressif/led_strip - idf -manifest_hash: 99de0774a8b78149b71d799483ddc6a488b7770b487a85a319b6a0d09f1d3ab9 +manifest_hash: 4baf2465d72df3c01363578f8fdebf1c18e30bd7ec1be43833075c7bcadab4fc target: esp32c6 version: 2.0.0 diff --git a/include/light_driver.h b/include/light_driver.h new file mode 100644 index 0000000..62ef658 --- /dev/null +++ b/include/light_driver.h @@ -0,0 +1,14 @@ +#ifndef LIGHT_DRIVER_H +#define LIGHT_DRIVER_H + +#define LIGHT_DEFAULT_OFF (0) +#define LIGHT_DEFAULT_ON (1) + +#include "esp_err.h" +#include "stdbool.h" + +esp_err_t light_driver_init(bool default_state); +esp_err_t light_driver_set_level(uint8_t level, uint16_t transition_ms); +esp_err_t light_driver_set_power(bool power, uint16_t transition_ms); + +#endif //LIGHT_DRIVER_H \ No newline at end of file diff --git a/include/zigbee.h b/include/zigbee.h new file mode 100644 index 0000000..b591845 --- /dev/null +++ b/include/zigbee.h @@ -0,0 +1,12 @@ +#ifndef ZIGBEE_H +#define ZIGBEE_H + +typedef struct zcl_basic_manufacturer_info_s { + char *manufacturer_name; + char *model_identifier; +} zcl_basic_manufacturer_info_t; + +void zigbee_init(void); +void zigbee_task(void* pvParameters); + +#endif \ No newline at end of file diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 397aead..95201c1 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,4 +1,5 @@ idf_component_register( SRC_DIRS "." - INCLUDE_DIRS "." + INCLUDE_DIRS "../include" + REQUIRES esp_driver_ledc nvs_flash ) diff --git a/main/esp_zb_light.h b/main/esp_zb_light.h deleted file mode 100644 index 3ec3da2..0000000 --- a/main/esp_zb_light.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: CC0-1.0 - * - * Zigbee HA_color_dimmable_light Example - * - * This example code is in the Public Domain (or CC0 licensed, at your option.) - * - * Unless required by applicable law or agreed to in writing, this - * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. - */ - -#include "esp_zigbee_core.h" -// #include "light_driver.h" -#include "zcl_utility.h" - -/* Zigbee configuration */ -#define MAX_CHILDREN 10 /* the max amount of connected devices */ -#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ -#define HA_COLOR_DIMMABLE_LIGHT_ENDPOINT 10 /* esp light switch device endpoint */ - -/* Basic manufacturer information */ -#define ESP_MANUFACTURER_NAME "\x09""ESPRESSIF" /* Customized manufacturer name */ -#define ESP_MODEL_IDENTIFIER "\x07"CONFIG_IDF_TARGET /* Customized model identifier */ - -#define ESP_ZB_ZR_CONFIG() \ - { \ - .esp_zb_role = ESP_ZB_DEVICE_TYPE_ROUTER, \ - .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ - .nwk_cfg.zczr_cfg = { \ - .max_children = MAX_CHILDREN, \ - }, \ - } - -#define ESP_ZB_DEFAULT_RADIO_CONFIG() \ - { \ - .radio_mode = ZB_RADIO_MODE_NATIVE, \ - } - -#define ESP_ZB_DEFAULT_HOST_CONFIG() \ - { \ - .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, \ - } diff --git a/main/idf_component.yml b/main/idf_component.yml index 198da01..ad32c63 100644 --- a/main/idf_component.yml +++ b/main/idf_component.yml @@ -2,7 +2,6 @@ dependencies: espressif/esp-zboss-lib: "~1.6.0" espressif/esp-zigbee-lib: "~1.6.0" - espressif/led_strip: "~2.0.0" ## Required IDF version idf: version: ">=5.0.0" diff --git a/main/light_driver.c b/main/light_driver.c new file mode 100644 index 0000000..febc929 --- /dev/null +++ b/main/light_driver.c @@ -0,0 +1,67 @@ +#include "light_driver.h" + +#include + +#include "driver/ledc.h" +#include "esp_log.h" +#include "esp_err.h" +#include + +static const char* TAG = "light_driver"; + +static const uint8_t light_gpio = 15; +static const uint16_t light_pwm_freq = 20000; +static const ledc_channel_t light_ledc_channel = LEDC_CHANNEL_0; +static const ledc_mode_t light_ledc_mode = LEDC_LOW_SPEED_MODE; +static const ledc_timer_bit_t light_pwm_resolution = LEDC_TIMER_10_BIT; +static const uint32_t light_max_brightness = (1 << light_pwm_resolution) - 1; +static const uint32_t light_max_level = 254; // zigbee light level, goes from 0 to 254 + +static bool light_init_done = false; +static uint8_t light_current_level = 0; + +esp_err_t light_driver_set_level(const uint8_t level, const uint16_t transition_ms) { + if (!light_init_done) { + ESP_LOGW(TAG, "light driver not ready!"); + return ESP_FAIL; + } + + light_current_level = level; + double brightness = (double)light_current_level / (double)light_max_level; + if (brightness > 1) brightness = 1; + if (brightness < 0) brightness = 0; + const uint32_t duty = (uint32_t)(light_max_brightness * brightness * brightness); // brightness^2 for fast gamma correction + ESP_ERROR_CHECK(ledc_set_fade_with_time(light_ledc_mode, light_ledc_channel, duty, transition_ms)); + ESP_ERROR_CHECK(ledc_fade_start(light_ledc_mode, light_ledc_channel, LEDC_FADE_NO_WAIT)); + return ESP_OK; +} + +esp_err_t light_driver_set_power(const bool power, const uint16_t transition_ms) { + return light_driver_set_level(power ? light_current_level : 0, transition_ms); +} + +esp_err_t light_driver_init(const bool default_state) { + const ledc_timer_config_t ledc_timer = { + .speed_mode = light_ledc_mode, + .duty_resolution = light_pwm_resolution, + .timer_num = LEDC_TIMER_2, + .freq_hz = light_pwm_freq, + .clk_cfg = LEDC_AUTO_CLK + }; + const ledc_channel_config_t ledc_channel = { + .speed_mode = ledc_timer.speed_mode, + .channel = light_ledc_channel, + .timer_sel = ledc_timer.timer_num, + .intr_type = LEDC_INTR_DISABLE, + .gpio_num = light_gpio, + .duty = 0, // Set duty to 0% + .hpoint = 0 + }; + ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer)); + ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel)); + ESP_ERROR_CHECK(ledc_fade_func_install(0)); + ESP_LOGI(TAG, "light driver inited, f=%d Hz", light_pwm_freq); + light_init_done = true; + light_driver_set_power(default_state, 100); + return ESP_OK; +} \ No newline at end of file diff --git a/main/main.c b/main/main.c new file mode 100644 index 0000000..ac0f518 --- /dev/null +++ b/main/main.c @@ -0,0 +1,10 @@ +#include "nvs_flash.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "zigbee.h" + + +void app_main(void) { + ESP_ERROR_CHECK(nvs_flash_init()); + xTaskCreate(zigbee_task, "Zigbee_main", 4096, NULL, 5, NULL); +} diff --git a/main/zcl_utility.c b/main/zcl_utility.c deleted file mode 100644 index ec72c48..0000000 --- a/main/zcl_utility.c +++ /dev/null @@ -1,22 +0,0 @@ -#include "zcl_utility.h" -#include -#include "esp_check.h" -#include "stdio.h" -#include "string.h" - -static const char *TAG = "ZCL_UTILITY"; - -esp_err_t esp_zcl_utility_add_ep_basic_manufacturer_info(esp_zb_ep_list_t *ep_list, const uint8_t endpoint_id, const zcl_basic_manufacturer_info_t *info) { - esp_zb_cluster_list_t *cluster_list = NULL; - esp_zb_attribute_list_t *basic_cluster = NULL; - - cluster_list = esp_zb_ep_list_get_ep(ep_list, endpoint_id); - ESP_RETURN_ON_FALSE(cluster_list, ESP_ERR_INVALID_ARG, TAG, "Failed to find endpoint id: %d in list: %p", endpoint_id, ep_list); - basic_cluster = esp_zb_cluster_list_get_cluster(cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); - ESP_RETURN_ON_FALSE(basic_cluster, ESP_ERR_INVALID_ARG, TAG, "Failed to find basic cluster in endpoint: %d", endpoint_id); - ESP_RETURN_ON_FALSE((info && info->manufacturer_name), ESP_ERR_INVALID_ARG, TAG, "Invalid manufacturer name"); - ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, info->manufacturer_name)); - ESP_RETURN_ON_FALSE((info && info->model_identifier), ESP_ERR_INVALID_ARG, TAG, "Invalid model identifier"); - ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, info->model_identifier)); - return ESP_OK; -} diff --git a/main/zcl_utility.h b/main/zcl_utility.h deleted file mode 100644 index c08a9d3..0000000 --- a/main/zcl_utility.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: CC0-1.0 - * - * Zigbee light driver example - * - * This example code is in the Public Domain (or CC0 licensed, at your option.) - * - * Unless required by applicable law or agreed to in writing, this - * software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, either express or implied. - */ - -#pragma once - -#ifdef __cplusplus -extern "C" { -#endif - -#include "esp_err.h" -#include "esp_check.h" -#include "esp_zigbee_core.h" - -/*! Maximum length of ManufacturerName string field */ -#define ESP_ZB_ZCL_CLUSTER_ID_BASIC_MANUFACTURER_NAME_MAX_LEN 32 - -/*! Maximum length of ModelIdentifier string field */ -#define ESP_ZB_ZCL_CLUSTER_ID_BASIC_MODEL_IDENTIFIER_MAX_LEN 32 - -/** optional basic manufacturer information */ -typedef struct zcl_basic_manufacturer_info_s { - char *manufacturer_name; - char *model_identifier; -} zcl_basic_manufacturer_info_t; - -/** - * @brief Adds manufacturer information to the ZCL basic cluster of endpoint - * - * @param[in] ep_list The pointer to the endpoint list with @p endpoint_id - * @param[in] endpoint_id The endpoint identifier indicating where the ZCL basic cluster resides - * @param[in] info The pointer to the basic manufacturer information - * @return - * - ESP_OK: On success - * - ESP_ERR_INVALID_ARG: Invalid argument - */ -esp_err_t esp_zcl_utility_add_ep_basic_manufacturer_info(esp_zb_ep_list_t *ep_list, uint8_t endpoint_id, const zcl_basic_manufacturer_info_t *info); - -#ifdef __cplusplus -} // extern "C" -#endif \ No newline at end of file diff --git a/main/esp_zb_light.c b/main/zigbee.c similarity index 60% rename from main/esp_zb_light.c rename to main/zigbee.c index 0e4cf68..f1086b4 100644 --- a/main/esp_zb_light.c +++ b/main/zigbee.c @@ -1,21 +1,21 @@ -#include "esp_zb_light.h" -#include "esp_check.h" -#include "esp_log.h" -#include "nvs_flash.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "ha/esp_zigbee_ha_standard.h" +// #include "ha/esp_zigbee_ha_standard.h" +#include "zigbee.h" +#include "esp_zigbee_core.h" +#include "light_driver.h" +#include +#include +#include -#if !defined CONFIG_ZB_ZCZR -#error Define ZB_ZCZR in idf.py menuconfig to compile light (Router) source code. -#endif +static const char* TAG = "zigbee"; + +static char manufacturer[] = "\x05""Drath"; +static char model[] = "\x15""Dimmable Zigbee Light"; +static const uint8_t endpoint_no = 1; -static const char* TAG = "ESP_ZB_COLOR_DIMM_LIGHT"; -/********************* Define functions **************************/ static esp_err_t deferred_driver_init(void) { static bool is_inited = false; if (!is_inited) { - // light_driver_init(LIGHT_DEFAULT_OFF); + light_driver_init(LIGHT_DEFAULT_OFF); is_inited = true; } return is_inited ? ESP_OK : ESP_FAIL; @@ -25,7 +25,150 @@ static void bdb_start_top_level_commissioning_cb(const uint8_t mode_mask) { ESP_RETURN_ON_FALSE(esp_zb_bdb_start_top_level_commissioning(mode_mask) == ESP_OK, , TAG, "Failed to start Zigbee commissioning"); } -void esp_zb_app_signal_handler(const esp_zb_app_signal_t* signal_struct) { +esp_err_t zigbee_utility_add_ep_basic_manufacturer_info(esp_zb_ep_list_t *ep_list, const uint8_t endpoint_id, const zcl_basic_manufacturer_info_t *info) { + esp_zb_cluster_list_t *cluster_list = NULL; + esp_zb_attribute_list_t *basic_cluster = NULL; + + cluster_list = esp_zb_ep_list_get_ep(ep_list, endpoint_id); + ESP_RETURN_ON_FALSE(cluster_list, ESP_ERR_INVALID_ARG, TAG, "Failed to find endpoint id: %d in list: %p", endpoint_id, ep_list); + basic_cluster = esp_zb_cluster_list_get_cluster(cluster_list, ESP_ZB_ZCL_CLUSTER_ID_BASIC, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + ESP_RETURN_ON_FALSE(basic_cluster, ESP_ERR_INVALID_ARG, TAG, "Failed to find basic cluster in endpoint: %d", endpoint_id); + ESP_RETURN_ON_FALSE((info && info->manufacturer_name), ESP_ERR_INVALID_ARG, TAG, "Invalid manufacturer name"); + ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, info->manufacturer_name)); + ESP_RETURN_ON_FALSE((info && info->model_identifier), ESP_ERR_INVALID_ARG, TAG, "Invalid model identifier"); + ESP_ERROR_CHECK(esp_zb_basic_cluster_add_attr(basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, info->model_identifier)); + return ESP_OK; +} + + +static esp_err_t zigbee_attribute_handler(const esp_zb_zcl_set_attr_value_message_t* message) { + ESP_RETURN_ON_FALSE(message, ESP_FAIL, TAG, "Empty message"); + ESP_RETURN_ON_FALSE(message->info.status == ESP_ZB_ZCL_STATUS_SUCCESS, ESP_ERR_INVALID_ARG, TAG, "Received message: error status(%d)", message->info.status); + ESP_LOGI(TAG, "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, message->attribute.id, message->attribute.data.size); + + if (message->info.dst_endpoint == endpoint_no) { + const uint16_t transition = 200; // default 200ms transition + switch (message->info.cluster) { + + case ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY: + ESP_LOGI(TAG, "Identify requested"); + break; + + case ESP_ZB_ZCL_CLUSTER_ID_ON_OFF: + if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + bool light_state = false; + light_state = message->attribute.data.value ? *(bool*)message->attribute.data.value : light_state; + ESP_LOGI(TAG, "Light sets to %s", light_state ? "On" : "Off"); + light_driver_set_power(light_state, transition); + } + else { ESP_LOGW(TAG, "On/Off cluster data: attribute(0x%x), type(0x%x)", message->attribute.id, message->attribute.data.type); } + break; + + case ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL: + if (message->attribute.id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { + uint8_t light_level = 0; + light_level = message->attribute.data.value ? *(uint8_t*)message->attribute.data.value : light_level; + light_driver_set_level(light_level, transition); + ESP_LOGI(TAG, "Light level changes to %d", light_level); + } + else + ESP_LOGW(TAG, "Level Control cluster data: attribute(0x%x), type(0x%x)", message->attribute.id, message->attribute.data.type); + break; + + default: + ESP_LOGI(TAG, "Message data: cluster(0x%x), attribute(0x%x) ", message->info.cluster, message->attribute.id); + } + } + return ESP_OK; +} + +static esp_err_t zigbee_action_handler(esp_zb_core_action_callback_id_t callback_id, const void* message) { + esp_err_t ret = ESP_OK; + switch (callback_id) { + + case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: + ret = zigbee_attribute_handler((esp_zb_zcl_set_attr_value_message_t*)message); + break; + + default: + ESP_LOGW(TAG, "Receive Zigbee action(0x%x) callback", callback_id); + break; + } + return ret; +} + + + +void zigbee_clusterfuck_init(esp_zb_cluster_list_t *cluster_list) { + esp_zb_basic_cluster_cfg_t basic_cfg = { + .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, + .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DC_SOURCE, + }; + + esp_zb_identify_cluster_cfg_t identify_cfg = { + .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE + }; + + esp_zb_groups_cluster_cfg_t group_cfg = { + .groups_name_support_id = ESP_ZB_ZCL_GROUPS_NAME_SUPPORT_DEFAULT_VALUE, + }; + + esp_zb_scenes_cluster_cfg_t scenes_cfg = { + .scenes_count = ESP_ZB_ZCL_SCENES_SCENE_COUNT_DEFAULT_VALUE, + .current_scene = ESP_ZB_ZCL_SCENES_CURRENT_SCENE_DEFAULT_VALUE, + .current_group = ESP_ZB_ZCL_SCENES_CURRENT_GROUP_DEFAULT_VALUE, + .scene_valid = ESP_ZB_ZCL_SCENES_SCENE_VALID_DEFAULT_VALUE, + .name_support = ESP_ZB_ZCL_SCENES_NAME_SUPPORT_DEFAULT_VALUE, + }; + + esp_zb_on_off_cluster_cfg_t on_off_cfg = { + .on_off = ESP_ZB_ZCL_ON_OFF_ON_OFF_DEFAULT_VALUE + }; + + esp_zb_level_cluster_cfg_t level_cfg = { + .current_level = ESP_ZB_ZCL_LEVEL_CONTROL_CURRENT_LEVEL_DEFAULT_VALUE, + }; + + // esp_zb_ota_cluster_cfg_t ota_cfg = { + // 0 + // }; + + esp_zb_attribute_list_t *basic_cluster = esp_zb_basic_cluster_create(&basic_cfg); + esp_zb_attribute_list_t *identify_cluster = esp_zb_identify_cluster_create(&identify_cfg); + esp_zb_attribute_list_t *groups_cluster = esp_zb_groups_cluster_create(&group_cfg); + esp_zb_attribute_list_t *scenes_cluster = esp_zb_scenes_cluster_create(&scenes_cfg); + esp_zb_attribute_list_t *on_off_cluster = esp_zb_on_off_cluster_create(&on_off_cfg); + esp_zb_attribute_list_t *level_cluster = esp_zb_level_cluster_create(&level_cfg); + // esp_zb_attribute_list_t *ota_cluster = esp_zb_ota_cluster_create(&ota_cfg); + + esp_zb_cluster_list_add_basic_cluster(cluster_list, basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_identify_cluster(cluster_list, identify_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_groups_cluster(cluster_list, groups_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_scenes_cluster(cluster_list, scenes_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_on_off_cluster(cluster_list, on_off_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + esp_zb_cluster_list_add_level_cluster(cluster_list, level_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); + // esp_zb_cluster_list_add_ota_cluster(cluster_list, ota_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); // disabling for now, not ready. maybe one day +} + +void zigbee_endpoint_init(esp_zb_ep_list_t *ep_list, esp_zb_cluster_list_t *cluster_list) { + const zcl_basic_manufacturer_info_t mfg_info = { + .manufacturer_name = manufacturer, + .model_identifier = model, + }; + + const esp_zb_endpoint_config_t ep_cfg = { + .endpoint = endpoint_no, + .app_device_id = 0x0101, + .app_profile_id = 0x0104, + .app_device_version = 0, + }; + + esp_zb_ep_list_add_ep(ep_list, cluster_list, ep_cfg); + zigbee_utility_add_ep_basic_manufacturer_info(ep_list, ep_cfg.endpoint, &mfg_info); +} + +/* appearently you cant rename this? */ +void esp_zb_app_signal_handler(esp_zb_app_signal_t* signal_struct) { uint32_t* p_sg_p = signal_struct->p_app_signal; const esp_err_t err_status = signal_struct->esp_err_status; const esp_zb_app_signal_type_t sig_type = *p_sg_p; @@ -46,7 +189,11 @@ void esp_zb_app_signal_handler(const esp_zb_app_signal_t* signal_struct) { ESP_LOGI(TAG, "Start network steering"); esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); } - else { ESP_LOGI(TAG, "Device rebooted"); } + else + { + ESP_LOGI(TAG, "Device rebooted, steering anyway"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); + } } else { ESP_LOGW(TAG, "%s failed with status: %s, retrying", esp_zb_zdo_signal_to_string(sig_type), @@ -86,141 +233,38 @@ void esp_zb_app_signal_handler(const esp_zb_app_signal_t* signal_struct) { } } -static esp_err_t zb_attribute_handler(const esp_zb_zcl_set_attr_value_message_t* message) { - ESP_RETURN_ON_FALSE(message, ESP_FAIL, TAG, "Empty message"); - ESP_RETURN_ON_FALSE(message->info.status == ESP_ZB_ZCL_STATUS_SUCCESS, ESP_ERR_INVALID_ARG, TAG, "Received message: error status(%d)", message->info.status); - ESP_LOGI(TAG, "Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, message->attribute.id, message->attribute.data.size); - - if (message->info.dst_endpoint == HA_COLOR_DIMMABLE_LIGHT_ENDPOINT) { - switch (message->info.cluster) { - - case ESP_ZB_ZCL_CLUSTER_ID_ON_OFF: - if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { - bool light_state = false; - light_state = message->attribute.data.value ? *(bool*)message->attribute.data.value : light_state; - ESP_LOGI(TAG, "Light sets to %s", light_state ? "On" : "Off"); - // light_driver_set_power(light_state); - } - else { ESP_LOGW(TAG, "On/Off cluster data: attribute(0x%x), type(0x%x)", message->attribute.id, message->attribute.data.type); } - break; - - case ESP_ZB_ZCL_CLUSTER_ID_COLOR_CONTROL: - ESP_LOGE(TAG, "we dont fuck with no color control in here"); - break; - - case ESP_ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL: - if (message->attribute.id == ESP_ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_U8) { - uint8_t light_level = 0; - light_level = message->attribute.data.value ? *(uint8_t*)message->attribute.data.value : light_level; - // light_driver_set_level((uint8_t)light_level); - ESP_LOGI(TAG, "Light level changes to %d", light_level); - } - else { ESP_LOGW(TAG, "Level Control cluster data: attribute(0x%x), type(0x%x)", message->attribute.id, message->attribute.data.type); } - break; - - default: - ESP_LOGI(TAG, "Message data: cluster(0x%x), attribute(0x%x) ", message->info.cluster, message->attribute.id); +void zigbee_task(void* pvParameters) { + esp_zb_platform_config_t zb_platform_config = { + .radio_config = { + .radio_mode = ZB_RADIO_MODE_NATIVE, + }, + .host_config = { + .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE, } - } - return ESP_OK; -} + }; -static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void* message) { - esp_err_t ret = ESP_OK; - switch (callback_id) { + esp_zb_cfg_t zb_nwk_cfg = { + .esp_zb_role = ESP_ZB_DEVICE_TYPE_ROUTER, + .install_code_policy = false, + .nwk_cfg.zczr_cfg = { + .max_children = 10, + }, + }; - case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: - ret = zb_attribute_handler((esp_zb_zcl_set_attr_value_message_t*)message); - break; - - default: - ESP_LOGW(TAG, "Receive Zigbee action(0x%x) callback", callback_id); - break; - } - return ret; -} - -static void esp_zb_task(void* pvParameters) { - /* initialize Zigbee stack */ - esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZR_CONFIG(); + ESP_ERROR_CHECK(esp_zb_platform_config(&zb_platform_config)); esp_zb_init(&zb_nwk_cfg); - const zcl_basic_manufacturer_info_t info = { - .manufacturer_name = ESP_MANUFACTURER_NAME, - .model_identifier = ESP_MODEL_IDENTIFIER, - }; - esp_zb_cluster_list_t *cluster_list = esp_zb_zcl_cluster_list_create(); + esp_zb_ep_list_t *endpoint_list = esp_zb_ep_list_create(); - esp_zb_basic_cluster_cfg_t basic_cfg = { - .zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, - .power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DC_SOURCE, - }; + zigbee_clusterfuck_init(cluster_list); + zigbee_endpoint_init(endpoint_list, cluster_list); - esp_zb_identify_cluster_cfg_t identify_cfg = { - .identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE - }; - - esp_zb_groups_cluster_cfg_t group_cfg = { - .groups_name_support_id = ESP_ZB_ZCL_GROUPS_NAME_SUPPORT_DEFAULT_VALUE, - }; - - esp_zb_scenes_cluster_cfg_t scenes_cfg = { - .scenes_count = ESP_ZB_ZCL_SCENES_SCENE_COUNT_DEFAULT_VALUE, - .current_scene = ESP_ZB_ZCL_SCENES_CURRENT_SCENE_DEFAULT_VALUE, - .current_group = ESP_ZB_ZCL_SCENES_CURRENT_GROUP_DEFAULT_VALUE, - .scene_valid = ESP_ZB_ZCL_SCENES_SCENE_VALID_DEFAULT_VALUE, - .name_support = ESP_ZB_ZCL_SCENES_NAME_SUPPORT_DEFAULT_VALUE, - }; - - esp_zb_on_off_cluster_cfg_t on_off_cfg = { - .on_off = ESP_ZB_ZCL_ON_OFF_ON_OFF_DEFAULT_VALUE - }; - - esp_zb_level_cluster_cfg_t level_cfg = { - .current_level = ESP_ZB_ZCL_LEVEL_CONTROL_CURRENT_LEVEL_DEFAULT_VALUE, - }; - - esp_zb_attribute_list_t *basic_cluster = esp_zb_basic_cluster_create(&basic_cfg); - esp_zb_attribute_list_t *identify_cluster = esp_zb_identify_cluster_create(&identify_cfg); - esp_zb_attribute_list_t *groups_cluster = esp_zb_groups_cluster_create(&group_cfg); - esp_zb_attribute_list_t *scenes_cluster = esp_zb_scenes_cluster_create(&scenes_cfg); - esp_zb_attribute_list_t *on_off_cluster = esp_zb_on_off_cluster_create(&on_off_cfg); - esp_zb_attribute_list_t *level_cluster = esp_zb_level_cluster_create(&level_cfg); - - esp_zb_cluster_list_add_basic_cluster(cluster_list, basic_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); - esp_zb_cluster_list_add_basic_cluster(cluster_list, identify_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); - esp_zb_cluster_list_add_basic_cluster(cluster_list, groups_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); - esp_zb_cluster_list_add_basic_cluster(cluster_list, scenes_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); - esp_zb_cluster_list_add_basic_cluster(cluster_list, on_off_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); - esp_zb_cluster_list_add_basic_cluster(cluster_list, level_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE); - - esp_zb_ep_list_t *ep_list = esp_zb_ep_list_create(); - - const esp_zb_endpoint_config_t ep_cfg = { - .endpoint = HA_COLOR_DIMMABLE_LIGHT_ENDPOINT, - .app_device_id = 0x0104, - .app_profile_id = 0x0101, - .app_device_version = 0, - }; - - esp_zb_ep_list_add_ep(ep_list, cluster_list, ep_cfg); - - - esp_zcl_utility_add_ep_basic_manufacturer_info(ep_list, HA_COLOR_DIMMABLE_LIGHT_ENDPOINT, &info); - esp_zb_device_register(ep_list); - esp_zb_core_action_handler_register(zb_action_handler); + esp_zb_device_register(endpoint_list); + esp_zb_core_action_handler_register(zigbee_action_handler); esp_zb_set_primary_network_channel_set(ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK); - ESP_ERROR_CHECK(esp_zb_start(false)); - esp_zb_stack_main_loop(); // blocking, holds the task here -} -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()); - ESP_ERROR_CHECK(esp_zb_platform_config(&config)); - xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); -} + ESP_ERROR_CHECK(esp_zb_start(false)); + + esp_zb_stack_main_loop(); // blocking, holds the task here +} \ No newline at end of file diff --git a/partitions.csv b/partitions.csv index a56c0be..15fb038 100644 --- a/partitions.csv +++ b/partitions.csv @@ -1,7 +1,11 @@ -# Name, Type, SubType, Offset, Size, Flags -# Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap -nvs, data, nvs, 0x9000, 0x6000, -phy_init, data, phy, 0xf000, 0x1000, -factory, app, factory, 0x10000, 900K, -zb_storage, data, fat, 0xf1000, 16K, -zb_fct, data, fat, 0xf5000, 1K, +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xf000, 0x1000, + +otadata, data, ota, 0x10000, 0x2000, + +ota_0, app, ota_0, , 900K, +ota_1, app, ota_1, , 900K, + +zb_storage, data, fat, , 16K, +zb_fct, data, fat, , 1K,