ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
task_log_buffer_esp32.cpp
Go to the documentation of this file.
1#ifdef USE_ESP32
2
4#include "esphome/core/log.h"
5
6#ifdef USE_ESPHOME_TASK_LOG_BUFFER
7
8namespace esphome::logger {
9
11 // Create a static ring buffer with RINGBUF_TYPE_NOSPLIT for message integrity
12 // Storage is a member array (embedded in Logger), no heap allocation needed
13 xRingbufferCreateStatic(sizeof(this->storage_), RINGBUF_TYPE_NOSPLIT, this->storage_, &this->structure_);
14}
15
17 if (this->current_token_) {
18 return false;
19 }
20
21 size_t item_size = 0;
22 void *received_item = xRingbufferReceive(this->handle_(), &item_size, 0);
23 if (received_item == nullptr) {
24 return false;
25 }
26
27 LogMessage *msg = static_cast<LogMessage *>(received_item);
28 message = msg;
29 text_length = msg->text_length;
30 this->current_token_ = received_item;
31
32 return true;
33}
34
36 if (this->current_token_ == nullptr) {
37 return;
38 }
39 vRingbufferReturnItem(this->handle_(), this->current_token_);
40 this->current_token_ = nullptr;
41 // Update counter to mark all messages as processed
42 last_processed_counter_ = message_counter_.load(std::memory_order_relaxed);
43}
44
45bool TaskLogBuffer::send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name,
46 const char *format, va_list args) {
47 // First, calculate the exact length needed using a null buffer (no actual writing)
48 va_list args_copy;
49 va_copy(args_copy, args);
50 int ret = vsnprintf(nullptr, 0, format, args_copy);
51 va_end(args_copy);
52
53 if (ret <= 0) {
54 return false; // Formatting error or empty message
55 }
56
57 // Calculate actual text length (capped to maximum size)
58 static constexpr size_t MAX_TEXT_SIZE = 255;
59 size_t text_length = (static_cast<size_t>(ret) > MAX_TEXT_SIZE) ? MAX_TEXT_SIZE : ret;
60
61 // Calculate total size needed (header + text length + null terminator)
62 size_t total_size = sizeof(LogMessage) + text_length + 1;
63
64 // Acquire memory directly from the ring buffer
65 void *acquired_memory = nullptr;
66 BaseType_t result = xRingbufferSendAcquire(this->handle_(), &acquired_memory, total_size, 0);
67
68 if (result != pdTRUE || acquired_memory == nullptr) {
69 return false; // Failed to acquire memory
70 }
71
72 // Set up the message header in the acquired memory
73 LogMessage *msg = static_cast<LogMessage *>(acquired_memory);
74 msg->level = level;
75 msg->tag = tag;
76 msg->line = line;
77
78 // Store the thread name now instead of waiting until main loop processing
79 // This avoids crashes if the task completes or is deleted between when this message
80 // is enqueued and when it's processed by the main loop
81 if (thread_name != nullptr) {
82 strncpy(msg->thread_name, thread_name, sizeof(msg->thread_name) - 1);
83 msg->thread_name[sizeof(msg->thread_name) - 1] = '\0'; // Ensure null termination
84 } else {
85 msg->thread_name[0] = '\0'; // Empty string if no thread name
86 }
87
88 // Format the message text directly into the acquired memory
89 // We add 1 to text_length to ensure space for null terminator during formatting
90 char *text_area = msg->text_data();
91 ret = vsnprintf(text_area, text_length + 1, format, args);
92
93 // Handle unexpected formatting error
94 if (ret <= 0) {
95 vRingbufferReturnItem(this->handle_(), acquired_memory);
96 return false;
97 }
98
99 // Remove trailing newlines
100 while (text_length > 0 && text_area[text_length - 1] == '\n') {
101 text_length--;
102 }
103
104 msg->text_length = text_length;
105 // Complete the send operation with the acquired memory
106 result = xRingbufferSendComplete(this->handle_(), acquired_memory);
107
108 if (result != pdTRUE) {
109 return false; // Failed to complete the message send
110 }
111
112 // Message sent successfully, increment the counter
113 message_counter_.fetch_add(1, std::memory_order_relaxed);
114 return true;
115}
116
117} // namespace esphome::logger
118
119#endif // USE_ESPHOME_TASK_LOG_BUFFER
120#endif // USE_ESP32
bool borrow_message_main_loop(LogMessage *&message, uint16_t &text_length)
bool send_message_thread_safe(uint8_t level, const char *tag, uint16_t line, const char *thread_name, const char *format, va_list args)
const LogString * message
Definition component.cpp:35
int ret
const char * format
va_end(args)