14#ifdef USE_ESPHOME_TASK_LOG_BUFFER
19#if defined(USE_ESP8266)
20#include <HardwareSerial.h>
23#include <HardwareSerial.h>
29#include <driver/uart.h>
33#include <zephyr/kernel.h>
58 virtual void on_log(uint8_t level,
const char *tag,
const char *
message,
size_t message_len) = 0;
61#ifdef USE_LOGGER_LEVEL_LISTENERS
85#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
88 bool operator()(
const char *a,
const char *b)
const {
return strcmp(a, b) < 0; }
93static constexpr char LOG_LEVEL_COLOR_DIGIT[] = {
104static constexpr char LOG_LEVEL_LETTER_CHARS[] = {
115static constexpr uint16_t MAX_HEADER_SIZE = 128;
118static constexpr size_t MAX_POINTER_REPRESENTATION = 2 +
sizeof(
void *) * 2 + 1;
125#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_LIBRETINY)
126static constexpr bool WRITE_MSG_ADDS_NEWLINE =
false;
128static constexpr bool WRITE_MSG_ADDS_NEWLINE =
true;
131#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
144#if defined(USE_LIBRETINY) || defined(USE_ESP32_VARIANT_ESP32)
147#ifdef USE_LOGGER_USB_CDC
150#ifdef USE_LOGGER_USB_SERIAL_JTAG
178 explicit Logger(uint32_t baud_rate,
size_t tx_buffer_size);
179#ifdef USE_ESPHOME_TASK_LOG_BUFFER
182#if defined(USE_ESPHOME_TASK_LOG_BUFFER) || (defined(USE_ZEPHYR) && defined(USE_LOGGER_USB_CDC))
183 void loop()
override;
188#if defined(USE_ARDUINO) && !defined(USE_ESP32)
195#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
203#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
215 inline uint8_t
level_for(
const char *tag);
220#ifdef USE_LOGGER_LEVEL_LISTENERS
227 void log_vprintf_(uint8_t level,
const char *tag,
int line,
const char *format, va_list args);
228#ifdef USE_STORE_LOG_STR_IN_FLASH
229 void log_vprintf_(uint8_t level,
const char *tag,
int line,
const __FlashStringHelper *format,
240 va_list args,
char *buffer, uint16_t *buffer_at,
241 uint16_t buffer_size) {
242#if defined(USE_ESP32) || defined(USE_LIBRETINY)
244#elif defined(USE_ZEPHYR)
245 char buff[MAX_POINTER_REPRESENTATION];
255 if (*buffer_at >= buffer_size) {
256 buffer[buffer_size - 1] =
'\0';
258 buffer[*buffer_at] =
'\0';
265 if constexpr (!WRITE_MSG_ADDS_NEWLINE) {
271 if (*buffer_at < buffer_size) {
272 buffer[(*buffer_at)++] =
'\n';
273 }
else if (buffer_size > 0) {
275 buffer[buffer_size - 1] =
'\n';
276 *buffer_at = buffer_size;
309 uint16_t buffer_size) {
311 if (*buffer_at >= buffer_size)
313 const uint16_t available = buffer_size - *buffer_at;
320 memcpy(buffer + *buffer_at, value, copy_len);
321 *buffer_at += copy_len;
332#if defined(USE_ARDUINO) && !defined(USE_ESP32)
335#if defined(USE_ZEPHYR)
338#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
350#ifdef USE_LOGGER_RUNTIME_TAG_LEVELS
354#ifdef USE_LOGGER_LEVEL_LISTENERS
357#ifdef USE_ESPHOME_TASK_LOG_BUFFER
365#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_ZEPHYR)
377#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
384 k_tid_t current_task = k_current_get();
386 TaskHandle_t current_task = xTaskGetCurrentTaskHandle();
391#if defined(USE_ESP32)
392 return pcTaskGetName(current_task);
393#elif defined(USE_LIBRETINY)
394 return pcTaskGetTaskName(current_task);
395#elif defined(USE_ZEPHYR)
396 const char *name = k_thread_name_get(current_task);
401 std::snprintf(buff, MAX_POINTER_REPRESENTATION,
"%p", current_task);
413 return was_recursive;
434 static inline void copy_string(
char *buffer, uint16_t &pos,
const char *str) {
435 const size_t len = strlen(str);
437 memcpy(buffer + pos, str,
len);
446 buffer[pos++] =
'\033';
448 buffer[pos++] = (level == 1) ?
'1' :
'0';
451 buffer[pos++] = LOG_LEVEL_COLOR_DIGIT[level];
456 char *buffer, uint16_t *buffer_at, uint16_t buffer_size) {
457 uint16_t pos = *buffer_at;
459 if (pos + MAX_HEADER_SIZE > buffer_size)
470 buffer[pos++] = LOG_LEVEL_LETTER_CHARS[level];
478 if (line > 999) [[unlikely]] {
479 int thousands = line / 1000;
480 buffer[pos++] =
'0' + thousands;
481 line -= thousands * 1000;
483 int hundreds = line / 100;
484 int remainder = line - hundreds * 100;
485 int tens = remainder / 10;
486 buffer[pos++] =
'0' + hundreds;
487 buffer[pos++] =
'0' + tens;
488 buffer[pos++] =
'0' + (remainder - tens * 10);
491#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_ZEPHYR)
492 if (thread_name !=
nullptr) {
509 if (*buffer_at >= buffer_size)
511 const uint16_t remaining = buffer_size - *buffer_at;
513 const int ret = vsnprintf(buffer + *buffer_at, remaining, format, args);
522 uint16_t formatted_len = (ret >= remaining) ? (remaining - 1) : ret;
523 *buffer_at += formatted_len;
526 while (*buffer_at > 0 && buffer[*buffer_at - 1] ==
'\n') {
532 static constexpr uint16_t RESET_COLOR_LEN =
sizeof(ESPHOME_LOG_RESET_COLOR) - 1;
533 this->
write_body_to_buffer_(ESPHOME_LOG_RESET_COLOR, RESET_COLOR_LEN, buffer, buffer_at, buffer_size);
554 void on_log(uint8_t level,
const char *tag,
const char *
message,
size_t message_len)
override {
556 if (level <= this->
level_) {
void disable_loop()
Disable this component's loop.
void trigger(const Ts &...x)
Interface for receiving log messages without std::function overhead.
virtual void on_log(uint8_t level, const char *tag, const char *message, size_t message_len)=0
Logger component for all ESPHome logging.
std::vector< LogListener * > log_listeners_
void add_level_listener(LoggerLevelListener *listener)
Register a listener for log level changes.
void add_log_listener(LogListener *listener)
Register a log listener to receive log messages.
void HOT format_log_to_buffer_with_terminator_(uint8_t level, const char *tag, int line, const char *format, va_list args, char *buffer, uint16_t *buffer_at, uint16_t buffer_size)
void HOT log_message_to_buffer_and_send_(uint8_t level, const char *tag, int line, const char *format, va_list args)
void dump_config() override
void HOT format_body_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size, const char *format, va_list args)
uint32_t get_baud_rate() const
const LogString * get_uart_selection_()
uint8_t level_for(const char *tag)
bool HOT check_and_set_task_log_recursion_(bool is_main_task)
Stream * get_hw_serial() const
void log_vprintf_(uint8_t level, const char *tag, int line, const char *format, va_list args)
void create_pthread_key()
void pre_setup()
Set up this component.
const char *HOT get_thread_name_(#ifdef USE_ZEPHYR char *buff #endif)
void HOT write_footer_to_buffer_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size)
float get_setup_priority() const override
std::map< const char *, uint8_t, CStrCompare > log_levels_
UARTSelection get_uart() const
Get the UART used by the logger.
std::vector< LoggerLevelListener * > level_listeners_
void write_msg_(const char *msg, size_t len)
void disable_loop_when_buffer_empty_()
std::unique_ptr< logger::TaskLogBuffer > log_buffer_
static void copy_string(char *buffer, uint16_t &pos, const char *str)
pthread_key_t log_recursion_key_
uart_port_t get_uart_num() const
void init_log_buffer(size_t total_buffer_size)
void HOT write_tx_buffer_to_console_(uint16_t offset=0, uint16_t *length=nullptr)
void set_log_level(uint8_t level)
Set the default log level for this logger.
void set_baud_rate(uint32_t baud_rate)
Manually set the baud rate for serial, set to 0 to disable.
void set_uart_selection(UARTSelection uart_selection)
static void write_ansi_color_for_level(char *buffer, uint16_t &pos, uint8_t level)
bool global_recursion_guard_
Logger(uint32_t baud_rate, size_t tx_buffer_size)
void HOT reset_task_log_recursion_(bool is_main_task)
void write_body_to_buffer_(const char *value, size_t length, char *buffer, uint16_t *buffer_at, uint16_t buffer_size)
void HOT write_header_to_buffer_(uint8_t level, const char *tag, int line, const char *thread_name, char *buffer, uint16_t *buffer_at, uint16_t buffer_size)
bool main_task_recursion_guard_
void HOT add_newline_to_buffer_if_needed_(char *buffer, uint16_t *buffer_at, uint16_t buffer_size)
Interface for receiving log level changes without std::function overhead.
virtual void on_log_level_change(uint8_t level)=0
void on_log(uint8_t level, const char *tag, const char *message, size_t message_len) override
LoggerMessageTrigger(Logger *parent, uint8_t level)
UARTSelection
Enum for logging UART selection.
@ UART_SELECTION_UART0_SWAP
@ UART_SELECTION_USB_SERIAL_JTAG
bool operator()(const char *a, const char *b) const