diff --git a/esphome/components/script/script.h b/esphome/components/script/script.h index 165f90ed11..0d6c13130a 100644 --- a/esphome/components/script/script.h +++ b/esphome/components/script/script.h @@ -225,7 +225,7 @@ template class ScriptWaitAction : public Action, this->play_next_(x...); return; } - this->var_ = std::make_tuple(x...); + this->play_queue_.push([this, x...]() { this->play_next_(x...); }); this->loop(); } @@ -236,7 +236,11 @@ template class ScriptWaitAction : public Action, if (this->script_->is_running()) return; - this->play_next_tuple_(this->var_); + while (!this->play_queue_.empty()) { + auto play_next = this->play_queue_.front(); + play_next(); + this->play_queue_.pop(); + } } float get_setup_priority() const override { return setup_priority::DATA; } @@ -246,7 +250,7 @@ template class ScriptWaitAction : public Action, protected: C *script_; - std::tuple var_{}; + std::queue> play_queue_; }; } // namespace script diff --git a/esphome/core/base_automation.h b/esphome/core/base_automation.h index dcf7da2f21..5aeea631fb 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -6,6 +6,7 @@ #include "esphome/core/preferences.h" #include +#include namespace esphome { @@ -230,32 +231,30 @@ template class WhileAction : public Action { void add_then(const std::vector *> &actions) { this->then_.add_actions(actions); this->then_.add_action(new LambdaAction([this](Ts... x) { - if (this->num_running_ > 0 && this->condition_->check_tuple(this->var_)) { + if (this->num_running_ > 0 && this->condition_->check(x...)) { // play again if (this->num_running_ > 0) { - this->then_.play_tuple(this->var_); + this->then_.play(x...); } } else { // condition false, play next - this->play_next_tuple_(this->var_); + this->play_next_(x...); } })); } void play_complex(Ts... x) override { this->num_running_++; - // Store loop parameters - this->var_ = std::make_tuple(x...); // Initial condition check - if (!this->condition_->check_tuple(this->var_)) { + if (!this->condition_->check(x...)) { // If new condition check failed, stop loop if running this->then_.stop(); - this->play_next_tuple_(this->var_); + this->play_next_(x...); return; } if (this->num_running_ > 0) { - this->then_.play_tuple(this->var_); + this->then_.play(x...); } } @@ -267,7 +266,6 @@ template class WhileAction : public Action { protected: Condition *condition_; ActionList then_; - std::tuple var_{}; }; template class RepeatAction : public Action { @@ -279,7 +277,7 @@ template class RepeatAction : public Action { this->then_.add_action(new LambdaAction([this](uint32_t iteration, Ts... x) { iteration++; if (iteration >= this->count_.value(x...)) { - this->play_next_tuple_(this->var_); + this->play_next_(x...); } else { this->then_.play(iteration, x...); } @@ -288,11 +286,10 @@ template class RepeatAction : public Action { void play_complex(Ts... x) override { this->num_running_++; - this->var_ = std::make_tuple(x...); if (this->count_.value(x...) > 0) { this->then_.play(0, x...); } else { - this->play_next_tuple_(this->var_); + this->play_next_(x...); } } @@ -303,7 +300,6 @@ template class RepeatAction : public Action { protected: ActionList then_; - std::tuple var_; }; template class WaitUntilAction : public Action, public Component { @@ -321,12 +317,11 @@ template class WaitUntilAction : public Action, public Co } return; } - this->var_ = std::make_tuple(x...); - if (this->timeout_value_.has_value()) { - auto f = std::bind(&WaitUntilAction::play_next_, this, x...); - this->set_timeout("timeout", this->timeout_value_.value(x...), f); - } + auto now = millis(); + auto timeout = this->timeout_value_.optional_value(x...); + + this->var_queue_.emplace_front(now, timeout, std::make_tuple(x...)); this->loop(); } @@ -335,13 +330,22 @@ template class WaitUntilAction : public Action, public Co if (this->num_running_ == 0) return; - if (!this->condition_->check_tuple(this->var_)) { - return; - } + auto now = millis(); - this->cancel_timeout("timeout"); + this->var_queue_.remove_if([&](decltype(*this->var_queue_.cbegin()) &queued) { + auto start = std::get(queued); + auto timeout = std::get>(queued); + auto var = std::get>(queued); - this->play_next_tuple_(this->var_); + auto expired = timeout && (now - start) >= timeout; + + if (!expired && !this->condition_->check_tuple(var)) { + return false; + } + + this->play_next_tuple_(var); + return true; + }); } float get_setup_priority() const override { return setup_priority::DATA; } @@ -349,11 +353,11 @@ template class WaitUntilAction : public Action, public Co void play(Ts... x) override { /* ignore - see play_complex */ } - void stop() override { this->cancel_timeout("timeout"); } + void stop() override { this->var_queue_.clear(); } protected: Condition *condition_; - std::tuple var_{}; + std::list, std::tuple>> var_queue_{}; }; template class UpdateComponentAction : public Action {