#include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_system.h" #include "esp_log.h" #include "driver/uart.h" #include "string.h" #include "driver/gpio.h" #include "meter_zigbee.h" #include #define TAG "meter_zigbee" #define TXD_PIN (GPIO_NUM_17) #define RXD_PIN (GPIO_NUM_16) #define BUF_SIZE 128 #define RX_BUF_SIZE 14 #define VOLTAGE_CURRENT1_ATTR 0x0006 #define VOLTAGE_CURRENT2_ATTR 0x0007 #define VOLTAGE_CURRENT3_ATTR 0x0008 static TaskHandle_t meter_zigbee_task = NULL; static float l1_current = 0, l2_current = 0, l3_current = 0; static float decode_current(const uint8_t *buf) { return (buf[9] + (buf[8] << 8) + (buf[7] << 16)) / 100.0f; } static void decode_frame(const uint8_t *buf) { uint16_t attr_code = buf[1] | (buf[2] << 8); uint8_t size = buf[4]; if (size != 8) { ESP_LOGW(TAG, "Unexpected data size: %d", size); return; } float current = decode_current(buf); ESP_LOGI(TAG, "Attr 0x%04X - Current: %.2f A", attr_code, current); switch (attr_code) { case VOLTAGE_CURRENT1_ATTR: l1_current = current; break; case VOLTAGE_CURRENT2_ATTR: l2_current = current; break; case VOLTAGE_CURRENT3_ATTR: l3_current = current; break; default: ESP_LOGW(TAG, "Unknown attribute code: 0x%04X", attr_code); return; } float max_current = fmaxf(fmaxf(l1_current, l2_current), l3_current); ESP_LOGI(TAG, "Max current: %.2f A", max_current); } static void meter_zigbee_task_func(void *param) { ESP_LOGI(TAG, "Zigbee meter task started"); uint8_t *buf = malloc(RX_BUF_SIZE); if (!buf) { ESP_LOGE(TAG, "Memory allocation failed"); vTaskDelete(NULL); return; } while (1) { int len = uart_read_bytes(UART_NUM_1, buf, RX_BUF_SIZE, pdMS_TO_TICKS(1000)); if (len >= 10) { decode_frame(buf); } } free(buf); vTaskDelete(NULL); } int meter_zigbee_send_data(const char *data) { int len = strlen(data); int sent = uart_write_bytes(UART_NUM_1, data, len); ESP_LOGI(TAG, "Sent %d bytes", sent); return sent; } void meter_zigbee_start(void) { ESP_LOGI(TAG, "Starting Zigbee UART"); uart_config_t uart_config = { .baud_rate = 115200, .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 }; ESP_ERROR_CHECK(uart_param_config(UART_NUM_1, &uart_config)); ESP_ERROR_CHECK(uart_set_pin(UART_NUM_1, TXD_PIN, RXD_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)); ESP_ERROR_CHECK(uart_driver_install(UART_NUM_1, BUF_SIZE * 2, 0, 0, NULL,0)); xTaskCreate(meter_zigbee_task_func, "meter_zigbee_task", 4096, NULL, 5, &meter_zigbee_task); } void meter_zigbee_stop(void) { ESP_LOGI(TAG, "Stopping Zigbee UART"); if (meter_zigbee_task) { vTaskDelete(meter_zigbee_task); meter_zigbee_task = NULL; } uart_driver_delete(UART_NUM_1); }