#include "log_handler.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include static const char *TAG = "LOG_HANDLER"; // Ring buffer for logs #define LOG_BUFFER_SIZE 8192 static char log_buffer[LOG_BUFFER_SIZE]; static size_t log_write_pos = 0; static size_t log_read_pos = 0; static size_t log_count = 0; static SemaphoreHandle_t log_mutex = NULL; static bool log_initialized = false; // Vprintf callback for capturing logs static int log_vprintf_cb(const char *fmt, va_list args) { // First, call the default vprintf to output to console int ret = vprintf(fmt, args); // Then, capture to our ring buffer if (log_mutex && log_initialized) { char temp_buf[256]; int len = vsnprintf(temp_buf, sizeof(temp_buf), fmt, args); if (len > 0 && len < (int)sizeof(temp_buf)) { xSemaphoreTake(log_mutex, portMAX_DELAY); for (int i = 0; i < len; i++) { log_buffer[log_write_pos] = temp_buf[i]; log_write_pos = (log_write_pos + 1) % LOG_BUFFER_SIZE; if (log_count < LOG_BUFFER_SIZE) { log_count++; } else { // Buffer full, advance read position log_read_pos = (log_read_pos + 1) % LOG_BUFFER_SIZE; } } xSemaphoreGive(log_mutex); } } return ret; } esp_err_t log_handler_init(void) { if (log_initialized) { ESP_LOGW(TAG, "Log handler already initialized"); return ESP_OK; } ESP_LOGI(TAG, "Initializing log handler"); log_mutex = xSemaphoreCreateMutex(); if (!log_mutex) { ESP_LOGE(TAG, "Failed to create log mutex"); return ESP_ERR_NO_MEM; } log_write_pos = 0; log_read_pos = 0; log_count = 0; memset(log_buffer, 0, LOG_BUFFER_SIZE); // Set our custom vprintf function esp_log_set_vprintf(log_vprintf_cb); log_initialized = true; ESP_LOGI(TAG, "Log handler initialized"); return ESP_OK; } esp_err_t log_handler_deinit(void) { if (!log_initialized) { return ESP_OK; } ESP_LOGI(TAG, "Deinitializing log handler"); // Restore default vprintf esp_log_set_vprintf(vprintf); if (log_mutex) { vSemaphoreDelete(log_mutex); log_mutex = NULL; } log_initialized = false; return ESP_OK; } size_t log_get_buffer(char *buf, size_t buf_len) { if (!buf || buf_len == 0 || !log_mutex) { return 0; } xSemaphoreTake(log_mutex, portMAX_DELAY); size_t to_copy = (log_count < buf_len) ? log_count : buf_len; size_t copied = 0; for (size_t i = 0; i < to_copy; i++) { size_t pos = (log_read_pos + i) % LOG_BUFFER_SIZE; buf[copied++] = log_buffer[pos]; } xSemaphoreGive(log_mutex); return copied; } void log_clear_buffer(void) { if (!log_mutex) { return; } xSemaphoreTake(log_mutex, portMAX_DELAY); log_write_pos = 0; log_read_pos = 0; log_count = 0; xSemaphoreGive(log_mutex); } size_t log_get_size(void) { if (!log_mutex) { return 0; } xSemaphoreTake(log_mutex, portMAX_DELAY); size_t count = log_count; xSemaphoreGive(log_mutex); return count; }