diff --git a/esphome/components/interval/interval.h b/esphome/components/interval/interval.h index 8f904b104d..e419841e6c 100644 --- a/esphome/components/interval/interval.h +++ b/esphome/components/interval/interval.h @@ -1,6 +1,7 @@ #pragma once #include "esphome/core/component.h" +#include "esphome/core/log.h" #include "esphome/core/automation.h" namespace esphome { @@ -8,16 +9,12 @@ namespace interval { class IntervalTrigger : public Trigger<>, public PollingComponent { public: - void update() override { - if (this->started_) - this->trigger(); - } + void update() override { this->trigger(); } void setup() override { - if (this->startup_delay_ == 0) { - this->started_ = true; - } else { - this->set_timeout(this->startup_delay_, [this] { this->started_ = true; }); + if (this->startup_delay_ != 0) { + this->stop_poller(); + this->set_timeout(this->startup_delay_, [this] { this->start_poller(); }); } } @@ -25,7 +22,6 @@ class IntervalTrigger : public Trigger<>, public PollingComponent { protected: uint32_t startup_delay_{0}; - bool started_{false}; }; } // namespace interval diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index aec6c17786..a6a59d30d5 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -373,11 +373,10 @@ bool Component::has_overridden_loop() const { PollingComponent::PollingComponent(uint32_t update_interval) : update_interval_(update_interval) {} void PollingComponent::call_setup() { + // init the poller before calling setup, allowing setup to cancel it if desired + this->start_poller(); // Let the polling component subclass setup their HW. this->setup(); - - // init the poller - this->start_poller(); } void PollingComponent::start_poller() { diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index 9e66fd3432..fc5d43d262 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -17,6 +17,8 @@ static const char *const TAG = "scheduler"; static const uint32_t MAX_LOGICALLY_DELETED_ITEMS = 10; // Half the 32-bit range - used to detect rollovers vs normal time progression static constexpr uint32_t HALF_MAX_UINT32 = std::numeric_limits::max() / 2; +// max delay to start an interval sequence +static constexpr uint32_t MAX_INTERVAL_DELAY = 5000; // Uncomment to debug scheduler // #define ESPHOME_DEBUG_SCHEDULER @@ -100,9 +102,11 @@ void HOT Scheduler::set_timer_common_(Component *component, SchedulerItem::Type // Type-specific setup if (type == SchedulerItem::INTERVAL) { item->interval = delay; - // Calculate random offset (0 to interval/2) - uint32_t offset = (delay != 0) ? (random_uint32() % delay) / 2 : 0; + // first execution happens immediately after a random smallish offset + // Calculate random offset (0 to min(interval/2, 5s)) + uint32_t offset = (uint32_t) (std::min(delay / 2, MAX_INTERVAL_DELAY) * random_float()); item->next_execution_ = now + offset; + ESP_LOGV(TAG, "Scheduler interval for %s is %" PRIu32 "ms, offset %" PRIu32 "ms", name_cstr, delay, offset); } else { item->interval = 0; item->next_execution_ = now + delay;