diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 4e7c4e0c2a..5ef959a36c 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -32,6 +32,27 @@ static constexpr uint32_t HALF_MAX_UINT32 = std::numeric_limits::max() // max delay to start an interval sequence static constexpr uint32_t MAX_INTERVAL_DELAY = 5000; +// Helper struct for formatting scheduler item names consistently in logs +// Uses a stack buffer to avoid heap allocation +struct SchedulerNameLog { + char buffer[20]; // Enough for "id:4294967295" or "hash:0xFFFFFFFF" + + // Format a scheduler item name for logging + // Returns pointer to formatted string (either static_name or internal buffer) + const char *format(Scheduler::NameType name_type, const char *static_name, uint32_t hash_or_id) { + using NameType = Scheduler::NameType; + if (name_type == NameType::STATIC_STRING) { + return static_name ? static_name : "(null)"; + } else if (name_type == NameType::HASHED_STRING) { + snprintf(buffer, sizeof(buffer), "hash:0x%08" PRIX32, hash_or_id); + return buffer; + } else { // NUMERIC_ID + snprintf(buffer, sizeof(buffer), "id:%" PRIu32, hash_or_id); + return buffer; + } + } +}; + // Uncomment to debug scheduler // #define ESPHOME_DEBUG_SCHEDULER @@ -135,8 +156,9 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type // Calculate random offset (0 to min(interval/2, 5s)) uint32_t offset = (uint32_t) (std::min(delay / 2, MAX_INTERVAL_DELAY) * random_float()); item->set_next_execution(now + offset); + SchedulerNameLog name_log; ESP_LOGV(TAG, "Scheduler interval for %s is %" PRIu32 "ms, offset %" PRIu32 "ms", - name_type == NameType::STATIC_STRING ? static_name : "(id)", delay, offset); + name_log.format(name_type, static_name, hash_or_id), delay, offset); } else { item->interval = 0; item->set_next_execution(now + delay); @@ -156,7 +178,9 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type /* match_retry= */ true))) { // Skip scheduling - the retry was cancelled #ifdef ESPHOME_DEBUG_SCHEDULER - ESP_LOGD(TAG, "Skipping retry - found cancelled item"); + SchedulerNameLog skip_name_log; + ESP_LOGD(TAG, "Skipping retry '%s' - found cancelled item", + skip_name_log.format(name_type, static_name, hash_or_id)); #endif return; } @@ -260,12 +284,14 @@ void HOT Scheduler::set_retry_common_(Component *component, NameType name_type, if (initial_wait_time == SCHEDULER_DONT_RUN) return; + SchedulerNameLog name_log; ESP_LOGVV(TAG, "set_retry(name='%s', initial_wait_time=%" PRIu32 ", max_attempts=%u, backoff_factor=%0.1f)", - name_type == NameType::STATIC_STRING ? static_name : "(id)", initial_wait_time, max_attempts, + name_log.format(name_type, static_name, hash_or_id), initial_wait_time, max_attempts, backoff_increase_factor); if (backoff_increase_factor < 0.0001) { - ESP_LOGE(TAG, "backoff_factor %0.1f too small, using 1.0", backoff_increase_factor); + ESP_LOGE(TAG, "backoff_factor %0.1f too small, using 1.0: %s", backoff_increase_factor, + name_log.format(name_type, static_name, hash_or_id)); backoff_increase_factor = 1; }