110 lines
3.0 KiB
C
Executable File
110 lines
3.0 KiB
C
Executable File
#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 <math.h>
|
|
|
|
#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);
|
|
}
|