idf_component_register(
SRCS
- "esp_zb_light.c"
+ "aqi.c"
INCLUDE_DIRS "."
)
--- /dev/null
+/*
+ * 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 "nvs_flash.h"
+#include "esp_log.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "ha/esp_zigbee_ha_standard.h"
+#include "aqi.h"
+//#include "esp_sleep.h"
+
+/**
+ * @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
+
+
+
+typedef struct zdo_info_ctx_s {
+ uint8_t endpoint;
+ esp_zb_ieee_addr_t long_addr;
+} zdo_info_user_ctx_t;
+
+static short temp_list[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static const char *TAG = "aqi";
+static OW ow;
+static bool zig_connected = false;
+static uint16_t cur_pm25 = 0;
+
+static float pm25buffer[PM25BUFFERSIZE];
+static int pm25bufferindex = 0;
+
+/********************* 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)
+{
+ /* Implement some actions if needed when other cluster changed */
+ ESP_LOGI(TAG, "cluster:0x%x, attribute:0x%x changed ", cluster_id, attr_id);
+}
+
+
+bool init_temp(){
+ bool err = ow_init(&ow, GPIO);
+ if (err){
+ ESP_LOGI(TAG, "there was an error initing ow");
+ }
+ return err;
+}
+
+
+// add new value to ringbuffer and return average of all, downcast to uint16_t
+uint16_t new_pm25_average(float new_val){
+ pm25buffer[pm25bufferindex++] = new_val;
+ // rollover
+ if (pm25bufferindex == PM25BUFFERSIZE){
+ pm25bufferindex = 0;
+ }
+
+ float total = 0;
+ int count = 0;
+ for (int i = 0; i < PM25BUFFERSIZE; i++ ){
+ // ignore initial values
+ if ( pm25buffer[i] != -1.0 ){
+ total += pm25buffer[i];
+ count++;
+ }
+ }
+ uint16_t retval = (uint16_t)(total*100/count);
+ ESP_LOGI(TAG, "returning average pm25 to send: %d", retval);
+ return retval;
+
+}
+
+void init_pm25buffer(){
+ for (int i = 0; i < PM25BUFFERSIZE; i++){
+ pm25buffer[i] = -1.0;
+ }
+}
+void init_uart(void) {
+ const uart_config_t uart_config = {
+ .baud_rate = 9600,
+ .data_bits = UART_DATA_8_BITS,
+ .parity = UART_PARITY_DISABLE,
+ .stop_bits = UART_STOP_BITS_1,
+ .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
+ .source_clk = UART_SCLK_DEFAULT,
+ };
+ // We won't use a buffer for sending data.
+ uart_driver_install(UART_NUM_1, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
+ uart_param_config(UART_NUM_1, &uart_config);
+ uart_set_pin(UART_NUM_1, UART_TX_GPIO, UART_RX_GPIO, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
+}
+
+static short get_temp(){
+ if (ow_reset (&ow)) {
+ //puts ("slave(s) present");
+
+ // scan bus for slaves
+ uint64_t romcode[MAXDEVS];
+ int num_devs = ow_romsearch (&ow, romcode, MAXDEVS, OW_SEARCH_ROM);
+ /*printf("Found %d devices\n", num_devs);
+ for (int i = 0; i < num_devs; i += 1) {
+ printf("\t%d: 0x%llx\n", i, romcode[i]);
+ }
+ putchar ('\n');*/
+
+ // get temperature readings
+ if (num_devs > 0) {
+ // start temperature conversion in parallel on all devices
+ // (see ds18b20 datasheet)
+ ow_reset (&ow);
+ ow_send (&ow, OW_SKIP_ROM);
+ ow_send (&ow, DS18B20_CONVERT_T);
+
+ // wait for the conversions to finish
+ while (ow_read(&ow) == 0);
+
+ // read the result from each device
+ //for (int i = 0; i < num_devs; i += 1) {
+ ow_reset (&ow);
+ ow_send (&ow, OW_MATCH_ROM);
+ for (int b = 0; b < 64; b += 8) {
+ ow_send (&ow, romcode[0] >> b);
+ }
+ ow_send (&ow, DS18B20_READ_SCRATCHPAD);
+ int16_t temp = 0;
+ temp = ow_read (&ow) | (ow_read (&ow) << 8);
+ short retval = (short)temp/16.0*100;
+ return retval;
+ } else {
+ puts("no devs\n");
+ return(0x8000);
+ }
+ } else {
+ puts ("no slave\n");
+ return(0x8000);
+ }
+}
+
+static void send_report(uint8_t report_type){
+ ESP_LOGI(TAG, "sending report here");
+ esp_zb_zcl_report_attr_cmd_t des;
+
+ //uint8_t long_addy[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
+ //memcpy(des.zcl_basic_cmd.dst_addr_u.addr_long, long_addy, sizeof(esp_zb_ieee_addr_t));
+ //des.zcl_basic_cmd.dst_addr_u.addr_long = long_addy;
+ des.zcl_basic_cmd.dst_addr_u.addr_short = 0;
+ // 0xFFFCu;
+ des.zcl_basic_cmd.dst_endpoint = HA_ESP_TEMP_ENDPOINT;
+ des.zcl_basic_cmd.src_endpoint = HA_ESP_TEMP_ENDPOINT;
+ des.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
+ //ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
+ //des.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
+
+ if (report_type == TEMP_REPORT){
+ des.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
+ des.attributeID = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID;
+ } else if (report_type == PM25_REPORT){
+ des.clusterID = PM25CLUSTER;
+ des.attributeID = PM25MEASURED;
+ } else {
+ ESP_LOGW(TAG, "undefined report type, just returning");
+ return;
+ }
+ des.cluster_role=ESP_ZB_ZCL_CLUSTER_SERVER_ROLE;
+ ESP_ERROR_CHECK(esp_zb_zcl_report_attr_cmd_req(&des));
+ if (report_type == TEMP_REPORT){
+ ESP_LOGI(TAG, "sent temp report");
+ } else if (report_type == PM25_REPORT){
+ ESP_LOGI(TAG, "sent pm25 report");
+ }
+
+}
+
+bool verify_checksum(uint8_t* data){
+ int total = 0;
+
+ for (int i = 0; i < 30; i++){
+ total += data[i];
+ }
+ uint8_t check_high = (uint8_t)(total >> 8);
+ uint8_t check_low = (uint8_t)(total & 0x00ff);
+ //printf("check bytes for us are %02x and %02x\n", check_high, check_low);
+ return data[30] == check_high && data[31] == check_low;
+}
+
+float get_average_pm25(uint8_t* data, int data_size){
+ int total = 0;
+ int count = 0;
+ char search_prefix[2] = {0x42, 0x4d};
+ uint8_t* first_entry = (uint8_t*)strstr((char*)data, search_prefix);
+ int offset = first_entry - data;
+ ESP_LOGI(TAG, "first entry found at %p (offset %d)", (uint8_t*)first_entry, offset);
+ uint8_t* cur_entry = first_entry;
+ int pm25;
+ while (cur_entry + 32 < data + data_size){
+ //printf("doing one iteration\n");
+ //ESP_LOG_BUFFER_HEXDUMP(TAG, cur_entry, 32, ESP_LOG_INFO);
+ if (verify_checksum(cur_entry)){
+ pm25 = (data[12] << 8) + (data[13]);
+ //ESP_LOGI(TAG, "pm25 val: %d", pm25);
+ count++;
+ total += pm25;
+ } else {
+ ESP_LOGW(TAG, "checksum failed for uart, skipping entry");
+ }
+ cur_entry += 32;
+ }
+ if (count == 0){
+ return 0.0;
+ } else {
+ return ((float)total)/count;
+ }
+}
+
+static void monitoring_task(void* discard)
+{
+ bool tempsetup = init_temp();
+ //bool tempsetup = true;
+
+ uint8_t* data = (uint8_t*) malloc(RX_BUF_SIZE+1);
+ int length = 0;
+ for(;;){
+ ESP_LOGI(TAG, "free heap: %"PRIu32, esp_get_free_heap_size());
+ //temp_list[0] += 100;
+ if (tempsetup){
+ temp_list[0] = get_temp();
+ } else {
+ ESP_LOGI(TAG, "temp not setup, skipping update");
+ }
+ ESP_LOGI(TAG, "current: %d", temp_list[0]);
+
+ if (zig_connected == true){
+ ESP_ERROR_CHECK(uart_get_buffered_data_len(UART_NUM_1, (size_t*)&length));
+ const int rxBytes = uart_read_bytes(UART_NUM_1, data, length, 100);
+ if (rxBytes > 0) {
+ data[rxBytes] = 0;
+ //ESP_LOGI(TAG, "Read %d bytes: '%s'", rxBytes, data);
+ //ESP_LOG_BUFFER_HEXDUMP(TAG, data, rxBytes, ESP_LOG_INFO);
+ float cur_avg = get_average_pm25(data, rxBytes);
+ ESP_LOGI(TAG, "average from last 10 seconds pm25: %f", cur_avg);
+ ESP_LOGI(TAG, "setting attrib value and sending, I guess");
+ cur_pm25 = new_pm25_average(cur_avg);
+ esp_zb_zcl_set_attribute_val(HA_ESP_TEMP_ENDPOINT, PM25CLUSTER, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE,
+ PM25MEASURED, &cur_pm25, false);
+ send_report(PM25_REPORT);
+
+ } else {
+ ESP_LOGI(TAG, "Nothing seen from uart");
+ }
+
+ ESP_LOGI(TAG, "setting attrib value and sending, I guess");
+ esp_zb_zcl_set_attribute_val(HA_ESP_TEMP_ENDPOINT, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE,
+ ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &temp_list[0], false);
+ send_report(TEMP_REPORT);
+ // reg sleep for 1 second to clear out backlog, then light sleep
+ //ESP_LOGI(TAG, "light sleep starts in a second");
+ vTaskDelay( pdMS_TO_TICKS(10000) );
+ //ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(9000000));
+ //ESP_ERROR_CHECK(esp_light_sleep_start());
+
+ // now we've woken up I guess?
+ ESP_LOGI(TAG, "I have worken up after sleep, looping around");
+
+ } else {
+ ESP_LOGI(TAG, "zig not connected, skipping temp report (and staying awake)");
+ vTaskDelay( pdMS_TO_TICKS(10000) );
+ }
+
+ }
+ // uart buffer
+ free(data);
+
+ //esp_zb_scheduler_alarm((esp_zb_callback_t)monitoring_task, parm, 10000);
+}
+
+static void esp_zb_read_resp_cb(esp_zb_zcl_status_t status, uint16_t cluster_id, uint16_t attr_id, esp_zb_zcl_attr_type_t attr_type, void *value)
+{
+ ESP_LOGI(TAG, "Switch got read attribute response with status:%d,cluster_id:0x%x,attr_id:0x%x,value:%d,attr_type:0x%x", status, cluster_id, attr_id, *(uint8_t *)value, attr_type);
+}
+
+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;
+ ESP_LOGI(TAG, "enter signal handler");
+ 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:
+ //zig_connected = false;
+ if (err_status == ESP_OK) {
+ ESP_LOGI(TAG, "Start network steering");
+ esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING);
+ esp_zb_ieee_addr_t local_addy;
+ esp_zb_get_long_address(local_addy);
+ ESP_LOGI(TAG, "Local ZB address: 0x%02x%02x%02x%02x%02x%02x%02x%02x",
+ local_addy[7], local_addy[6], local_addy[5], local_addy[4],
+ local_addy[3], local_addy[2], local_addy[1], local_addy[0]);
+ /*char global[16] = ZB_DISTRIBUTED_GLOBAL_KEY
+ ESP_LOGI(TAG, "Pairs 0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ global[0], global[1], global[2], global[3],
+ global[4], global[5], global[6], global[7],
+ global[8], global[9], global[10], global[11],
+ global[12], global[13], global[14], global[15]
+ );
+ */
+
+ } else {
+ /* commissioning failed */
+ ESP_LOGW(TAG, "Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status));
+ //zig_connected = false;
+ esp_zb_start(false);
+ }
+ 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, Channel:%d)",
+ 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(), esp_zb_get_current_channel());
+ /* Implement some actions if needed when other cluster changed */
+
+ zig_connected = true;
+ } else {
+ ESP_LOGI(TAG, "Network steering was not successful (status: %s)", esp_err_to_name(err_status));
+ //zig_connected = false;
+ 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: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type,
+ esp_err_to_name(err_status));
+ break;
+ }
+}
+
+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(ESP_ZB_PRIMARY_CHANNEL_MASK);
+
+ /* set the on-off light device config */
+ char modelid[] = {7, 'T', 'E', 'S', 'T', 'D', 'E', 'V'};
+ char manufacturer[] = {3, 'h', 'e', 'x'};
+ uint8_t power_source[] = {0x01};
+
+
+ for (int i= 0; i < 10; i++ ){
+ temp_list[i] = 0x8000;
+ }
+ /* basic cluster create with fully customized */
+ esp_zb_attribute_list_t *esp_zb_basic_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_BASIC);
+ esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID, power_source);
+ esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, &modelid);
+ esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, &manufacturer);
+ /* identify cluster create with fully customized */
+ esp_zb_attribute_list_t *esp_zb_identify_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY);
+ /* group cluster create with fully customized */
+ //esp_zb_attribute_list_t *esp_zb_groups_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_GROUPS);
+ /* scenes cluster create with standard cluster + customized */
+ //esp_zb_attribute_list_t *esp_zb_scenes_cluster = esp_zb_scenes_cluster_create(NULL);
+ /* on-off cluster create with standard cluster config*/
+ //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);
+
+
+ // color control cluster
+ //esp_zb_attribute_list_t *esp_zb_color_cluster = esp_zb_color_control_cluster_create(NULL);
+
+ // level cluster
+ //esp_zb_attribute_list_t *esp_zb_level_cluster = esp_zb_level_cluster_create(NULL);
+
+ short min_temp = -5500;
+ short max_temp = 12500;
+ // temperature cluster
+ esp_zb_attribute_list_t *esp_zb_temp_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT);
+ esp_zb_temperature_meas_cluster_add_attr(esp_zb_temp_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &temp_list[0]);
+ esp_zb_temperature_meas_cluster_add_attr(esp_zb_temp_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, &min_temp);
+ esp_zb_temperature_meas_cluster_add_attr(esp_zb_temp_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, &max_temp);
+
+
+ esp_zb_attribute_list_t *esp_zb_pm25_cluster = esp_zb_zcl_attr_list_create(PM25CLUSTER);
+ ESP_ERROR_CHECK(esp_zb_custom_cluster_add_custom_attr(esp_zb_pm25_cluster, PM25MEASURED, ESP_ZB_ZCL_ATTR_TYPE_U16, ESP_ZB_ZCL_ATTR_ACCESS_READ_ONLY | ESP_ZB_ZCL_ATTR_ACCESS_REPORTING, &cur_pm25));
+
+ /* create cluster lists for this endpoint */
+ 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);
+
+ // add all the clusters to our main cluster list
+ //esp_zb_cluster_list_update_basic_cluster(esp_zb_cluster_list, esp_zb_basic_cluster_create(NULL), 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_temperature_meas_cluster(esp_zb_cluster_list, esp_zb_temp_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
+ ESP_ERROR_CHECK(esp_zb_cluster_list_add_custom_cluster(esp_zb_cluster_list, esp_zb_pm25_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE));
+
+
+ esp_zb_ep_list_t *esp_zb_ep_list = esp_zb_ep_list_create();
+ /* add created endpoint (cluster_list) to endpoint list */
+ esp_zb_ep_list_add_ep(esp_zb_ep_list, esp_zb_cluster_list, HA_ESP_TEMP_ENDPOINT, ESP_ZB_AF_HA_PROFILE_ID, ESP_ZB_HA_ON_OFF_OUTPUT_DEVICE_ID);
+ esp_zb_device_register(esp_zb_ep_list);
+
+ // set first pm25 val
+ /*esp_zb_zcl_set_attribute_val(HA_ESP_TEMP_ENDPOINT, PM25CLUSTER, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE,
+ PM25MEASURED, &cur_pm25, false);*/
+
+ // set first temp value
+ esp_zb_zcl_set_attribute_val(HA_ESP_TEMP_ENDPOINT, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE,
+ ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &temp_list[0], false);
+
+ //esp_zb_device_add_set_attr_value_cb(attr_cb);
+ esp_zb_add_read_attr_resp_cb(HA_ESP_TEMP_ENDPOINT, esp_zb_read_resp_cb);
+ ESP_ERROR_CHECK(esp_zb_start(false));
+
+ //ESP_ERROR_CHECK(esp_zb_secur_ic_set(ESP_ZB_IC_TYPE_128, (uint8_t*)curic));
+ ESP_LOGI(TAG, "main loop begin");
+ 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());
+ init_uart();
+ init_pm25buffer();
+ /* 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);
+ xTaskCreate(monitoring_task, "monitoring_task", 4096, NULL, 1, NULL);
+}
--- /dev/null
+/*
+ * 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 "esp_system.h"
+//#include "light_driver.h"
+
+
+#include "driver/uart.h"
+#include "string.h"
+#include "driver/gpio.h"
+#include "onewire.h"
+
+#define GPIO 2
+#define MAXDEVS 10
+#define UART_RX_GPIO (GPIO_NUM_26)
+#define UART_TX_GPIO (GPIO_NUM_27)
+#define PM25CLUSTER 0xFFFE
+//0x042A
+#define PM25MEASURED 0x0000
+
+#define TEMP_REPORT 0x1
+#define PM25_REPORT 0x2
+
+
+#define PM25BUFFERSIZE 6
+
+static const int RX_BUF_SIZE = 1024;
+
+//#define ZB_DISTRIBUTED_GLOBAL_KEY {0x1, 0x3, 0x5, 0x7, 0x9, 0xb, 0xd, 0xf, 0x0, 0x2, 0x4, 0x6, 0x8, 0xa, 0xc, 0xd};
+
+// Generic ROM commands for 1-Wire devices
+// https://www.analog.com/en/technical-articles/guide-to-1wire-communication.html
+//
+#define OW_READ_ROM 0x33
+#define OW_MATCH_ROM 0x55
+#define OW_SKIP_ROM 0xCC
+#define OW_ALARM_SEARCH 0xEC
+#define OW_SEARCH_ROM 0xF0
+
+// Function commands for d218b20 1-Wire temperature sensor
+// https://www.analog.com/en/products/ds18b20.html
+//
+#define DS18B20_CONVERT_T 0x44
+#define DS18B20_WRITE_SCRATCHPAD 0x4e
+#define DS18B20_READ_SCRATCHPAD 0xbe
+#define DS18B20_COPY_SCRATCHPAD 0x48
+#define DS18B20_RECALL_EE 0xb8
+#define DS18B20_READ_POWER_SUPPLY 0xb4
+
+
+
+/* Zigbee configuration */
+#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */
+#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN
+#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */
+#define HA_ESP_TEMP_ENDPOINT 1
+#define HA_ESP_LIGHT_ENDPOINT 1 /* esp light bulb device endpoint, used to process light controlling commands */
+#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */
+//specifically search channel 15, which is what I'm on
+//#define ESP_ZB_PRIMARY_CHANNEL_MASK 1l<<15
+
+#define ESP_ZB_ZED_CONFIG() \
+ { \
+ .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, \
+ .install_code_policy = INSTALLCODE_POLICY_ENABLE, \
+ .nwk_cfg.zed_cfg = { \
+ .ed_timeout = ED_AGING_TIMEOUT, \
+ .keep_alive = ED_KEEP_ALIVE, \
+ }, \
+ }
+
+#define ESP_ZB_DEFAULT_RADIO_CONFIG() \
+ { \
+ .radio_mode = RADIO_MODE_NATIVE, \
+ }
+
+#define ESP_ZB_DEFAULT_HOST_CONFIG() \
+ { \
+ .host_connection_mode = HOST_CONNECTION_MODE_NONE, \
+ }
+++ /dev/null
-/*
- * 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 "nvs_flash.h"
-#include "esp_log.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/task.h"
-#include "ha/esp_zigbee_ha_standard.h"
-#include "esp_zb_light.h"
-//#include "esp_sleep.h"
-
-/**
- * @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
-
-
-
-typedef struct zdo_info_ctx_s {
- uint8_t endpoint;
- esp_zb_ieee_addr_t long_addr;
-} zdo_info_user_ctx_t;
-
-static short temp_list[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
-static const char *TAG = "aqi";
-static OW ow;
-static bool zig_connected = false;
-static uint16_t cur_pm25 = 0;
-
-static float pm25buffer[PM25BUFFERSIZE];
-static int pm25bufferindex = 0;
-
-/********************* 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)
-{
- /* Implement some actions if needed when other cluster changed */
- ESP_LOGI(TAG, "cluster:0x%x, attribute:0x%x changed ", cluster_id, attr_id);
-}
-
-
-bool init_temp(){
- bool err = ow_init(&ow, GPIO);
- if (err){
- ESP_LOGI(TAG, "there was an error initing ow");
- }
- return err;
-}
-
-
-// add new value to ringbuffer and return average of all, downcast to uint16_t
-uint16_t new_pm25_average(float new_val){
- pm25buffer[pm25bufferindex++] = new_val;
- // rollover
- if (pm25bufferindex == PM25BUFFERSIZE){
- pm25bufferindex = 0;
- }
-
- float total = 0;
- int count = 0;
- for (int i = 0; i < PM25BUFFERSIZE; i++ ){
- // ignore initial values
- if ( pm25buffer[i] != -1.0 ){
- total += pm25buffer[i];
- count++;
- }
- }
- uint16_t retval = (uint16_t)(total*100/count);
- ESP_LOGI(TAG, "returning average pm25 to send: %d", retval);
- return retval;
-
-}
-
-void init_pm25buffer(){
- for (int i = 0; i < PM25BUFFERSIZE; i++){
- pm25buffer[i] = -1.0;
- }
-}
-void init_uart(void) {
- const uart_config_t uart_config = {
- .baud_rate = 9600,
- .data_bits = UART_DATA_8_BITS,
- .parity = UART_PARITY_DISABLE,
- .stop_bits = UART_STOP_BITS_1,
- .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
- .source_clk = UART_SCLK_DEFAULT,
- };
- // We won't use a buffer for sending data.
- uart_driver_install(UART_NUM_1, RX_BUF_SIZE * 2, 0, 0, NULL, 0);
- uart_param_config(UART_NUM_1, &uart_config);
- uart_set_pin(UART_NUM_1, UART_TX_GPIO, UART_RX_GPIO, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
-}
-
-static short get_temp(){
- if (ow_reset (&ow)) {
- //puts ("slave(s) present");
-
- // scan bus for slaves
- uint64_t romcode[MAXDEVS];
- int num_devs = ow_romsearch (&ow, romcode, MAXDEVS, OW_SEARCH_ROM);
- /*printf("Found %d devices\n", num_devs);
- for (int i = 0; i < num_devs; i += 1) {
- printf("\t%d: 0x%llx\n", i, romcode[i]);
- }
- putchar ('\n');*/
-
- // get temperature readings
- if (num_devs > 0) {
- // start temperature conversion in parallel on all devices
- // (see ds18b20 datasheet)
- ow_reset (&ow);
- ow_send (&ow, OW_SKIP_ROM);
- ow_send (&ow, DS18B20_CONVERT_T);
-
- // wait for the conversions to finish
- while (ow_read(&ow) == 0);
-
- // read the result from each device
- //for (int i = 0; i < num_devs; i += 1) {
- ow_reset (&ow);
- ow_send (&ow, OW_MATCH_ROM);
- for (int b = 0; b < 64; b += 8) {
- ow_send (&ow, romcode[0] >> b);
- }
- ow_send (&ow, DS18B20_READ_SCRATCHPAD);
- int16_t temp = 0;
- temp = ow_read (&ow) | (ow_read (&ow) << 8);
- short retval = (short)temp/16.0*100;
- return retval;
- } else {
- puts("no devs\n");
- return(0x8000);
- }
- } else {
- puts ("no slave\n");
- return(0x8000);
- }
-}
-
-static void send_report(uint8_t report_type){
- ESP_LOGI(TAG, "sending report here");
- esp_zb_zcl_report_attr_cmd_t des;
-
- //uint8_t long_addy[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff};
- //memcpy(des.zcl_basic_cmd.dst_addr_u.addr_long, long_addy, sizeof(esp_zb_ieee_addr_t));
- //des.zcl_basic_cmd.dst_addr_u.addr_long = long_addy;
- des.zcl_basic_cmd.dst_addr_u.addr_short = 0;
- // 0xFFFCu;
- des.zcl_basic_cmd.dst_endpoint = HA_ESP_TEMP_ENDPOINT;
- des.zcl_basic_cmd.src_endpoint = HA_ESP_TEMP_ENDPOINT;
- des.address_mode = ESP_ZB_APS_ADDR_MODE_16_ENDP_PRESENT;
- //ESP_ZB_APS_ADDR_MODE_16_GROUP_ENDP_NOT_PRESENT;
- //des.address_mode = ESP_ZB_APS_ADDR_MODE_64_ENDP_PRESENT;
-
- if (report_type == TEMP_REPORT){
- des.clusterID = ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT;
- des.attributeID = ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID;
- } else if (report_type == PM25_REPORT){
- des.clusterID = PM25CLUSTER;
- des.attributeID = PM25MEASURED;
- } else {
- ESP_LOGW(TAG, "undefined report type, just returning");
- return;
- }
- des.cluster_role=ESP_ZB_ZCL_CLUSTER_SERVER_ROLE;
- ESP_ERROR_CHECK(esp_zb_zcl_report_attr_cmd_req(&des));
- if (report_type == TEMP_REPORT){
- ESP_LOGI(TAG, "sent temp report");
- } else if (report_type == PM25_REPORT){
- ESP_LOGI(TAG, "sent pm25 report");
- }
-
-}
-
-bool verify_checksum(uint8_t* data){
- int total = 0;
-
- for (int i = 0; i < 30; i++){
- total += data[i];
- }
- uint8_t check_high = (uint8_t)(total >> 8);
- uint8_t check_low = (uint8_t)(total & 0x00ff);
- //printf("check bytes for us are %02x and %02x\n", check_high, check_low);
- return data[30] == check_high && data[31] == check_low;
-}
-
-float get_average_pm25(uint8_t* data, int data_size){
- int total = 0;
- int count = 0;
- char search_prefix[2] = {0x42, 0x4d};
- uint8_t* first_entry = (uint8_t*)strstr((char*)data, search_prefix);
- int offset = first_entry - data;
- ESP_LOGI(TAG, "first entry found at %p (offset %d)", (uint8_t*)first_entry, offset);
- uint8_t* cur_entry = first_entry;
- int pm25;
- while (cur_entry + 32 < data + data_size){
- //printf("doing one iteration\n");
- //ESP_LOG_BUFFER_HEXDUMP(TAG, cur_entry, 32, ESP_LOG_INFO);
- if (verify_checksum(cur_entry)){
- pm25 = (data[12] << 8) + (data[13]);
- //ESP_LOGI(TAG, "pm25 val: %d", pm25);
- count++;
- total += pm25;
- } else {
- ESP_LOGW(TAG, "checksum failed for uart, skipping entry");
- }
- cur_entry += 32;
- }
- if (count == 0){
- return 0.0;
- } else {
- return ((float)total)/count;
- }
-}
-
-static void monitoring_task(void* discard)
-{
- bool tempsetup = init_temp();
- //bool tempsetup = true;
-
- uint8_t* data = (uint8_t*) malloc(RX_BUF_SIZE+1);
- int length = 0;
- for(;;){
- ESP_LOGI(TAG, "free heap: %"PRIu32, esp_get_free_heap_size());
- //temp_list[0] += 100;
- if (tempsetup){
- temp_list[0] = get_temp();
- } else {
- ESP_LOGI(TAG, "temp not setup, skipping update");
- }
- ESP_LOGI(TAG, "current: %d", temp_list[0]);
-
- if (zig_connected == true){
- ESP_ERROR_CHECK(uart_get_buffered_data_len(UART_NUM_1, (size_t*)&length));
- const int rxBytes = uart_read_bytes(UART_NUM_1, data, length, 100);
- if (rxBytes > 0) {
- data[rxBytes] = 0;
- //ESP_LOGI(TAG, "Read %d bytes: '%s'", rxBytes, data);
- //ESP_LOG_BUFFER_HEXDUMP(TAG, data, rxBytes, ESP_LOG_INFO);
- float cur_avg = get_average_pm25(data, rxBytes);
- ESP_LOGI(TAG, "average from last 10 seconds pm25: %f", cur_avg);
- ESP_LOGI(TAG, "setting attrib value and sending, I guess");
- cur_pm25 = new_pm25_average(cur_avg);
- esp_zb_zcl_set_attribute_val(HA_ESP_TEMP_ENDPOINT, PM25CLUSTER, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE,
- PM25MEASURED, &cur_pm25, false);
- send_report(PM25_REPORT);
-
- } else {
- ESP_LOGI(TAG, "Nothing seen from uart");
- }
-
- ESP_LOGI(TAG, "setting attrib value and sending, I guess");
- esp_zb_zcl_set_attribute_val(HA_ESP_TEMP_ENDPOINT, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE,
- ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &temp_list[0], false);
- send_report(TEMP_REPORT);
- // reg sleep for 1 second to clear out backlog, then light sleep
- //ESP_LOGI(TAG, "light sleep starts in a second");
- vTaskDelay( pdMS_TO_TICKS(10000) );
- //ESP_ERROR_CHECK(esp_sleep_enable_timer_wakeup(9000000));
- //ESP_ERROR_CHECK(esp_light_sleep_start());
-
- // now we've woken up I guess?
- ESP_LOGI(TAG, "I have worken up after sleep, looping around");
-
- } else {
- ESP_LOGI(TAG, "zig not connected, skipping temp report (and staying awake)");
- vTaskDelay( pdMS_TO_TICKS(10000) );
- }
-
- }
- // uart buffer
- free(data);
-
- //esp_zb_scheduler_alarm((esp_zb_callback_t)monitoring_task, parm, 10000);
-}
-
-static void esp_zb_read_resp_cb(esp_zb_zcl_status_t status, uint16_t cluster_id, uint16_t attr_id, esp_zb_zcl_attr_type_t attr_type, void *value)
-{
- ESP_LOGI(TAG, "Switch got read attribute response with status:%d,cluster_id:0x%x,attr_id:0x%x,value:%d,attr_type:0x%x", status, cluster_id, attr_id, *(uint8_t *)value, attr_type);
-}
-
-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;
- ESP_LOGI(TAG, "enter signal handler");
- 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:
- //zig_connected = false;
- if (err_status == ESP_OK) {
- ESP_LOGI(TAG, "Start network steering");
- esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING);
- esp_zb_ieee_addr_t local_addy;
- esp_zb_get_long_address(local_addy);
- ESP_LOGI(TAG, "Local ZB address: 0x%02x%02x%02x%02x%02x%02x%02x%02x",
- local_addy[7], local_addy[6], local_addy[5], local_addy[4],
- local_addy[3], local_addy[2], local_addy[1], local_addy[0]);
- /*char global[16] = ZB_DISTRIBUTED_GLOBAL_KEY
- ESP_LOGI(TAG, "Pairs 0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
- global[0], global[1], global[2], global[3],
- global[4], global[5], global[6], global[7],
- global[8], global[9], global[10], global[11],
- global[12], global[13], global[14], global[15]
- );
- */
-
- } else {
- /* commissioning failed */
- ESP_LOGW(TAG, "Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status));
- //zig_connected = false;
- esp_zb_start(false);
- }
- 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, Channel:%d)",
- 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(), esp_zb_get_current_channel());
- /* Implement some actions if needed when other cluster changed */
-
- zig_connected = true;
- } else {
- ESP_LOGI(TAG, "Network steering was not successful (status: %s)", esp_err_to_name(err_status));
- //zig_connected = false;
- 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: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type,
- esp_err_to_name(err_status));
- break;
- }
-}
-
-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(ESP_ZB_PRIMARY_CHANNEL_MASK);
-
- /* set the on-off light device config */
- char modelid[] = {7, 'T', 'E', 'S', 'T', 'D', 'E', 'V'};
- char manufacturer[] = {3, 'h', 'e', 'x'};
- uint8_t power_source[] = {0x01};
-
-
- for (int i= 0; i < 10; i++ ){
- temp_list[i] = 0x8000;
- }
- /* basic cluster create with fully customized */
- esp_zb_attribute_list_t *esp_zb_basic_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_BASIC);
- esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_POWER_SOURCE_ID, power_source);
- esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MODEL_IDENTIFIER_ID, &modelid);
- esp_zb_basic_cluster_add_attr(esp_zb_basic_cluster, ESP_ZB_ZCL_ATTR_BASIC_MANUFACTURER_NAME_ID, &manufacturer);
- /* identify cluster create with fully customized */
- esp_zb_attribute_list_t *esp_zb_identify_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_IDENTIFY);
- /* group cluster create with fully customized */
- //esp_zb_attribute_list_t *esp_zb_groups_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_GROUPS);
- /* scenes cluster create with standard cluster + customized */
- //esp_zb_attribute_list_t *esp_zb_scenes_cluster = esp_zb_scenes_cluster_create(NULL);
- /* on-off cluster create with standard cluster config*/
- //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);
-
-
- // color control cluster
- //esp_zb_attribute_list_t *esp_zb_color_cluster = esp_zb_color_control_cluster_create(NULL);
-
- // level cluster
- //esp_zb_attribute_list_t *esp_zb_level_cluster = esp_zb_level_cluster_create(NULL);
-
- short min_temp = -5500;
- short max_temp = 12500;
- // temperature cluster
- esp_zb_attribute_list_t *esp_zb_temp_cluster = esp_zb_zcl_attr_list_create(ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT);
- esp_zb_temperature_meas_cluster_add_attr(esp_zb_temp_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &temp_list[0]);
- esp_zb_temperature_meas_cluster_add_attr(esp_zb_temp_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MIN_VALUE_ID, &min_temp);
- esp_zb_temperature_meas_cluster_add_attr(esp_zb_temp_cluster, ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_MAX_VALUE_ID, &max_temp);
-
-
- esp_zb_attribute_list_t *esp_zb_pm25_cluster = esp_zb_zcl_attr_list_create(PM25CLUSTER);
- ESP_ERROR_CHECK(esp_zb_custom_cluster_add_custom_attr(esp_zb_pm25_cluster, PM25MEASURED, ESP_ZB_ZCL_ATTR_TYPE_U16, ESP_ZB_ZCL_ATTR_ACCESS_READ_ONLY | ESP_ZB_ZCL_ATTR_ACCESS_REPORTING, &cur_pm25));
-
- /* create cluster lists for this endpoint */
- 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);
-
- // add all the clusters to our main cluster list
- //esp_zb_cluster_list_update_basic_cluster(esp_zb_cluster_list, esp_zb_basic_cluster_create(NULL), 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_temperature_meas_cluster(esp_zb_cluster_list, esp_zb_temp_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE);
- ESP_ERROR_CHECK(esp_zb_cluster_list_add_custom_cluster(esp_zb_cluster_list, esp_zb_pm25_cluster, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE));
-
-
- esp_zb_ep_list_t *esp_zb_ep_list = esp_zb_ep_list_create();
- /* add created endpoint (cluster_list) to endpoint list */
- esp_zb_ep_list_add_ep(esp_zb_ep_list, esp_zb_cluster_list, HA_ESP_TEMP_ENDPOINT, ESP_ZB_AF_HA_PROFILE_ID, ESP_ZB_HA_ON_OFF_OUTPUT_DEVICE_ID);
- esp_zb_device_register(esp_zb_ep_list);
-
- // set first pm25 val
- /*esp_zb_zcl_set_attribute_val(HA_ESP_TEMP_ENDPOINT, PM25CLUSTER, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE,
- PM25MEASURED, &cur_pm25, false);*/
-
- // set first temp value
- esp_zb_zcl_set_attribute_val(HA_ESP_TEMP_ENDPOINT, ESP_ZB_ZCL_CLUSTER_ID_TEMP_MEASUREMENT, ESP_ZB_ZCL_CLUSTER_SERVER_ROLE,
- ESP_ZB_ZCL_ATTR_TEMP_MEASUREMENT_VALUE_ID, &temp_list[0], false);
-
- //esp_zb_device_add_set_attr_value_cb(attr_cb);
- esp_zb_add_read_attr_resp_cb(HA_ESP_TEMP_ENDPOINT, esp_zb_read_resp_cb);
- ESP_ERROR_CHECK(esp_zb_start(false));
-
- //ESP_ERROR_CHECK(esp_zb_secur_ic_set(ESP_ZB_IC_TYPE_128, (uint8_t*)curic));
- ESP_LOGI(TAG, "main loop begin");
- 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());
- init_uart();
- init_pm25buffer();
- /* 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);
- xTaskCreate(monitoring_task, "monitoring_task", 4096, NULL, 1, NULL);
-}
+++ /dev/null
-/*
- * 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 "esp_system.h"
-//#include "light_driver.h"
-
-
-#include "driver/uart.h"
-#include "string.h"
-#include "driver/gpio.h"
-#include "onewire.h"
-
-#define GPIO 2
-#define MAXDEVS 10
-#define UART_RX_GPIO (GPIO_NUM_26)
-#define UART_TX_GPIO (GPIO_NUM_27)
-#define PM25CLUSTER 0xFFFE
-//0x042A
-#define PM25MEASURED 0x0000
-
-#define TEMP_REPORT 0x1
-#define PM25_REPORT 0x2
-
-
-#define PM25BUFFERSIZE 6
-
-static const int RX_BUF_SIZE = 1024;
-
-//#define ZB_DISTRIBUTED_GLOBAL_KEY {0x1, 0x3, 0x5, 0x7, 0x9, 0xb, 0xd, 0xf, 0x0, 0x2, 0x4, 0x6, 0x8, 0xa, 0xc, 0xd};
-
-// Generic ROM commands for 1-Wire devices
-// https://www.analog.com/en/technical-articles/guide-to-1wire-communication.html
-//
-#define OW_READ_ROM 0x33
-#define OW_MATCH_ROM 0x55
-#define OW_SKIP_ROM 0xCC
-#define OW_ALARM_SEARCH 0xEC
-#define OW_SEARCH_ROM 0xF0
-
-// Function commands for d218b20 1-Wire temperature sensor
-// https://www.analog.com/en/products/ds18b20.html
-//
-#define DS18B20_CONVERT_T 0x44
-#define DS18B20_WRITE_SCRATCHPAD 0x4e
-#define DS18B20_READ_SCRATCHPAD 0xbe
-#define DS18B20_COPY_SCRATCHPAD 0x48
-#define DS18B20_RECALL_EE 0xb8
-#define DS18B20_READ_POWER_SUPPLY 0xb4
-
-
-
-/* Zigbee configuration */
-#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */
-#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN
-#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */
-#define HA_ESP_TEMP_ENDPOINT 1
-#define HA_ESP_LIGHT_ENDPOINT 1 /* esp light bulb device endpoint, used to process light controlling commands */
-#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */
-//specifically search channel 15, which is what I'm on
-//#define ESP_ZB_PRIMARY_CHANNEL_MASK 1l<<15
-
-#define ESP_ZB_ZED_CONFIG() \
- { \
- .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, \
- .install_code_policy = INSTALLCODE_POLICY_ENABLE, \
- .nwk_cfg.zed_cfg = { \
- .ed_timeout = ED_AGING_TIMEOUT, \
- .keep_alive = ED_KEEP_ALIVE, \
- }, \
- }
-
-#define ESP_ZB_DEFAULT_RADIO_CONFIG() \
- { \
- .radio_mode = RADIO_MODE_NATIVE, \
- }
-
-#define ESP_ZB_DEFAULT_HOST_CONFIG() \
- { \
- .host_connection_mode = HOST_CONNECTION_MODE_NONE, \
- }