diff --git a/esphome/core/component.cpp b/esphome/core/component.cpp index 7505e1f39b..b1ace8b2d1 100644 --- a/esphome/core/component.cpp +++ b/esphome/core/component.cpp @@ -57,7 +57,7 @@ bool Component::cancel_interval(const std::string &name) { // NOLINT } void Component::set_retry(const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, - std::function &&f, float backoff_increase_factor) { // NOLINT + std::function &&f, float backoff_increase_factor) { // NOLINT App.scheduler.set_retry(this, name, initial_wait_time, max_attempts, std::move(f), backoff_increase_factor); } @@ -130,7 +130,7 @@ void Component::set_timeout(uint32_t timeout, std::function &&f) { // N void Component::set_interval(uint32_t interval, std::function &&f) { // NOLINT App.scheduler.set_interval(this, "", interval, std::move(f)); } -void Component::set_retry(uint32_t initial_wait_time, uint8_t max_attempts, std::function &&f, +void Component::set_retry(uint32_t initial_wait_time, uint8_t max_attempts, std::function &&f, float backoff_increase_factor) { // NOLINT App.scheduler.set_retry(this, "", initial_wait_time, max_attempts, std::move(f), backoff_increase_factor); } diff --git a/esphome/core/component.h b/esphome/core/component.h index 3b873cbc9f..769e74e645 100644 --- a/esphome/core/component.h +++ b/esphome/core/component.h @@ -193,6 +193,9 @@ class Component { * increased by multipling by `backoff_increase_factor` each time. If no backoff_increase_factor is * supplied (default = 1.0), the wait time will stay constant. * + * The retry function f needs to accept a single argument: the number of attempts remaining. On the + * final retry of f, this value will be 0. + * * This retry function can also be cancelled by name via cancel_retry(). * * IMPORTANT: Do not rely on this having correct timing. This is only called from @@ -210,11 +213,11 @@ class Component { * @param backoff_increase_factor time between retries is multiplied by this factor on every retry after the first * @see cancel_retry() */ - void set_retry(const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, // NOLINT - std::function &&f, float backoff_increase_factor = 1.0f); // NOLINT + void set_retry(const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, // NOLINT + std::function &&f, float backoff_increase_factor = 1.0f); // NOLINT - void set_retry(uint32_t initial_wait_time, uint8_t max_attempts, std::function &&f, // NOLINT - float backoff_increase_factor = 1.0f); // NOLINT + void set_retry(uint32_t initial_wait_time, uint8_t max_attempts, std::function &&f, // NOLINT + float backoff_increase_factor = 1.0f); // NOLINT /** Cancel a retry function. * diff --git a/esphome/core/scheduler.cpp b/esphome/core/scheduler.cpp index dfec4fcaa2..d880f0fda4 100644 --- a/esphome/core/scheduler.cpp +++ b/esphome/core/scheduler.cpp @@ -74,7 +74,7 @@ bool HOT Scheduler::cancel_interval(Component *component, const std::string &nam } struct RetryArgs { - std::function func; + std::function func; uint8_t retry_countdown; uint32_t current_interval; Component *component; @@ -84,17 +84,18 @@ struct RetryArgs { }; static void retry_handler(const std::shared_ptr &args) { - RetryResult retry_result = args->func(); - if (retry_result == RetryResult::DONE || --args->retry_countdown <= 0) + RetryResult const retry_result = args->func(--args->retry_countdown); + if (retry_result == RetryResult::DONE || args->retry_countdown <= 0) return; - // second execution of `func` hapens after `initial_wait_time` + // second execution of `func` happens after `initial_wait_time` args->scheduler->set_timeout(args->component, args->name, args->current_interval, [args]() { retry_handler(args); }); // backoff_increase_factor applied to third & later executions args->current_interval *= args->backoff_increase_factor; } void HOT Scheduler::set_retry(Component *component, const std::string &name, uint32_t initial_wait_time, - uint8_t max_attempts, std::function func, float backoff_increase_factor) { + uint8_t max_attempts, std::function func, + float backoff_increase_factor) { if (!name.empty()) this->cancel_retry(component, name); diff --git a/esphome/core/scheduler.h b/esphome/core/scheduler.h index 111bee1df2..a758198b8d 100644 --- a/esphome/core/scheduler.h +++ b/esphome/core/scheduler.h @@ -16,7 +16,7 @@ class Scheduler { bool cancel_interval(Component *component, const std::string &name); void set_retry(Component *component, const std::string &name, uint32_t initial_wait_time, uint8_t max_attempts, - std::function func, float backoff_increase_factor = 1.0f); + std::function func, float backoff_increase_factor = 1.0f); bool cancel_retry(Component *component, const std::string &name); optional next_schedule_in(); diff --git a/tests/test2.yaml b/tests/test2.yaml index 7d4cb4cbb2..2c94333c03 100644 --- a/tests/test2.yaml +++ b/tests/test2.yaml @@ -462,6 +462,15 @@ binary_sensor: name: Mi Motion Sensor 2 Light button: name: Mi Motion Sensor 2 Button + - platform: gpio + id: gpio_set_retry_test + pin: GPIO9 + on_press: + then: + - lambda: |- + App.scheduler.set_retry(id(gpio_set_retry_test), "set_retry_test", 100, 3, [](const uint8_t remaining) { + return remaining ? RetryResult::RETRY : RetryResult::DONE; // just to reference both symbols + }, 5.0f); esp32_ble_tracker: on_ble_advertise: