works so far, just tweaks left

This commit is contained in:
2026-03-15 22:07:15 +01:00
parent 223d38c295
commit a671f7f33e
14 changed files with 321 additions and 290 deletions

View File

@@ -5,6 +5,5 @@ cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/../esp-zigbee-sdk/components) set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/../esp-zigbee-sdk/components)
include($ENV{IDF_PATH}/tools/cmake/project.cmake) include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(st7290) project(zigbee_light)
idf_build_set_property(CXX_COMPILE_OPTIONS "-Wno-missing-field-initializers" APPEND) idf_build_set_property(CXX_COMPILE_OPTIONS "-Wno-missing-field-initializers" APPEND)

13
README.md Normal file
View File

@@ -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?

View File

@@ -6,8 +6,7 @@ dependencies:
type: local type: local
version: 1.6.8 version: 1.6.8
espressif/cmake_utilities: espressif/cmake_utilities:
component_hash: component_hash: 351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f
351350613ceafba240b761b4ea991e0f231ac7a9f59a9ee901f751bddc0bb18f
dependencies: dependencies:
- name: idf - name: idf
require: private require: private
@@ -17,8 +16,7 @@ dependencies:
type: service type: service
version: 0.5.3 version: 0.5.3
espressif/esp-zboss-lib: espressif/esp-zboss-lib:
component_hash: component_hash: 321883d142421f65009972408287441794250057668a11abbdfd8bec77c3309a
321883d142421f65009972408287441794250057668a11abbdfd8bec77c3309a
dependencies: dependencies:
- name: idf - name: idf
require: private require: private
@@ -27,17 +25,6 @@ dependencies:
registry_url: https://components.espressif.com/ registry_url: https://components.espressif.com/
type: service type: service
version: 1.6.4 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: idf:
source: source:
type: idf type: idf
@@ -46,8 +33,7 @@ direct_dependencies:
- espressif/cmake_utilities - espressif/cmake_utilities
- espressif/esp-zboss-lib - espressif/esp-zboss-lib
- espressif/esp-zigbee-lib - espressif/esp-zigbee-lib
- espressif/led_strip
- idf - idf
manifest_hash: 99de0774a8b78149b71d799483ddc6a488b7770b487a85a319b6a0d09f1d3ab9 manifest_hash: 4baf2465d72df3c01363578f8fdebf1c18e30bd7ec1be43833075c7bcadab4fc
target: esp32c6 target: esp32c6
version: 2.0.0 version: 2.0.0

14
include/light_driver.h Normal file
View File

@@ -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

12
include/zigbee.h Normal file
View File

@@ -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

View File

@@ -1,4 +1,5 @@
idf_component_register( idf_component_register(
SRC_DIRS "." SRC_DIRS "."
INCLUDE_DIRS "." INCLUDE_DIRS "../include"
REQUIRES esp_driver_ledc nvs_flash
) )

View File

@@ -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, \
}

View File

@@ -2,7 +2,6 @@
dependencies: dependencies:
espressif/esp-zboss-lib: "~1.6.0" espressif/esp-zboss-lib: "~1.6.0"
espressif/esp-zigbee-lib: "~1.6.0" espressif/esp-zigbee-lib: "~1.6.0"
espressif/led_strip: "~2.0.0"
## Required IDF version ## Required IDF version
idf: idf:
version: ">=5.0.0" version: ">=5.0.0"

67
main/light_driver.c Normal file
View File

@@ -0,0 +1,67 @@
#include "light_driver.h"
#include <esp_zigbee_core.h>
#include "driver/ledc.h"
#include "esp_log.h"
#include "esp_err.h"
#include <stdbool.h>
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;
}

10
main/main.c Normal file
View File

@@ -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);
}

View File

@@ -1,22 +0,0 @@
#include "zcl_utility.h"
#include <stdint.h>
#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;
}

View File

@@ -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

View File

@@ -1,21 +1,21 @@
#include "esp_zb_light.h" // #include "ha/esp_zigbee_ha_standard.h"
#include "esp_check.h" #include "zigbee.h"
#include "esp_log.h" #include "esp_zigbee_core.h"
#include "nvs_flash.h" #include "light_driver.h"
#include "freertos/FreeRTOS.h" #include <esp_log.h>
#include "freertos/task.h" #include <esp_err.h>
#include "ha/esp_zigbee_ha_standard.h" #include <esp_check.h>
#if !defined CONFIG_ZB_ZCZR static const char* TAG = "zigbee";
#error Define ZB_ZCZR in idf.py menuconfig to compile light (Router) source code.
#endif 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 esp_err_t deferred_driver_init(void) {
static bool is_inited = false; static bool is_inited = false;
if (!is_inited) { if (!is_inited) {
// light_driver_init(LIGHT_DEFAULT_OFF); light_driver_init(LIGHT_DEFAULT_OFF);
is_inited = true; is_inited = true;
} }
return is_inited ? ESP_OK : ESP_FAIL; 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"); 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; uint32_t* p_sg_p = signal_struct->p_app_signal;
const esp_err_t err_status = signal_struct->esp_err_status; const esp_err_t err_status = signal_struct->esp_err_status;
const esp_zb_app_signal_type_t sig_type = *p_sg_p; 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_LOGI(TAG, "Start network steering");
esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_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 { else {
ESP_LOGW(TAG, "%s failed with status: %s, retrying", esp_zb_zdo_signal_to_string(sig_type), 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) { void zigbee_task(void* pvParameters) {
ESP_RETURN_ON_FALSE(message, ESP_FAIL, TAG, "Empty message"); esp_zb_platform_config_t zb_platform_config = {
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); .radio_config = {
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); .radio_mode = ZB_RADIO_MODE_NATIVE,
},
if (message->info.dst_endpoint == HA_COLOR_DIMMABLE_LIGHT_ENDPOINT) { .host_config = {
switch (message->info.cluster) { .host_connection_mode = ZB_HOST_CONNECTION_MODE_NONE,
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);
} }
} };
return ESP_OK;
}
static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void* message) { esp_zb_cfg_t zb_nwk_cfg = {
esp_err_t ret = ESP_OK; .esp_zb_role = ESP_ZB_DEVICE_TYPE_ROUTER,
switch (callback_id) { .install_code_policy = false,
.nwk_cfg.zczr_cfg = {
.max_children = 10,
},
};
case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: ESP_ERROR_CHECK(esp_zb_platform_config(&zb_platform_config));
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_zb_init(&zb_nwk_cfg); 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_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 = { zigbee_clusterfuck_init(cluster_list);
.zcl_version = ESP_ZB_ZCL_BASIC_ZCL_VERSION_DEFAULT_VALUE, zigbee_endpoint_init(endpoint_list, cluster_list);
.power_source = ESP_ZB_ZCL_BASIC_POWER_SOURCE_DC_SOURCE,
};
esp_zb_identify_cluster_cfg_t identify_cfg = { esp_zb_device_register(endpoint_list);
.identify_time = ESP_ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE esp_zb_core_action_handler_register(zigbee_action_handler);
};
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_set_primary_network_channel_set(ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK); 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_ERROR_CHECK(esp_zb_start(false));
esp_zb_platform_config_t config = {
.radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(), esp_zb_stack_main_loop(); // blocking, holds the task here
.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);
}

View File

@@ -1,7 +1,11 @@
# Name, Type, SubType, Offset, Size, Flags # 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,
nvs, data, nvs, 0x9000, 0x6000, phy_init, data, phy, 0xf000, 0x1000,
phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 900K, otadata, data, ota, 0x10000, 0x2000,
zb_storage, data, fat, 0xf1000, 16K,
zb_fct, data, fat, 0xf5000, 1K, ota_0, app, ota_0, , 900K,
ota_1, app, ota_1, , 900K,
zb_storage, data, fat, , 16K,
zb_fct, data, fat, , 1K,
1 # Name, Type, SubType, Offset, Size, Flags # Name Type SubType Offset Size Flags
2 # Note: if you have increased the bootloader size, make sure to update the offsets to avoid overlap nvs data nvs 0x9000 0x6000
3 nvs, data, nvs, 0x9000, 0x6000, phy_init data phy 0xf000 0x1000
4 phy_init, data, phy, 0xf000, 0x1000, otadata data ota 0x10000 0x2000
5 factory, app, factory, 0x10000, 900K, ota_0 app ota_0 900K
6 zb_storage, data, fat, 0xf1000, 16K, ota_1 app ota_1 900K
7 zb_fct, data, fat, 0xf5000, 1K, zb_storage data fat 16K
8 zb_fct data fat 1K
9
10
11