diff --git a/esphome/components/script/script.h b/esphome/components/script/script.h index 3b97327da8..a6b208167f 100644 --- a/esphome/components/script/script.h +++ b/esphome/components/script/script.h @@ -53,41 +53,34 @@ template class ScriptWaitAction : public Action, public C public: ScriptWaitAction(Script *script) : script_(script) {} - void play(Ts... x) { /* ignore - see play_complex */ + void play(Ts... x) override { /* ignore - see play_complex */ } void play_complex(Ts... x) override { + this->num_running_++; // Check if we can continue immediately. if (!this->script_->is_running()) { - this->triggered_ = false; this->play_next(x...); return; } this->var_ = std::make_tuple(x...); - this->triggered_ = true; this->loop(); } - void stop() override { this->triggered_ = false; } - void loop() override { - if (!this->triggered_) + if (this->num_running_ == 0) return; if (this->script_->is_running()) return; - this->triggered_ = false; this->play_next_tuple(this->var_); } float get_setup_priority() const override { return setup_priority::DATA; } - bool is_running() override { return this->triggered_ || this->is_running_next(); } - protected: Script *script_; - bool triggered_{false}; std::tuple var_{}; }; diff --git a/esphome/core/automation.h b/esphome/core/automation.h index cbe96a749e..6e595fc458 100644 --- a/esphome/core/automation.h +++ b/esphome/core/automation.h @@ -77,17 +77,24 @@ template class Action { public: virtual void play(Ts... x) = 0; virtual void play_complex(Ts... x) { + this->num_running_++; this->play(x...); this->play_next(x...); } void play_next(Ts... x) { - if (this->next_ != nullptr) { - this->next_->play_complex(x...); + if (this->num_running_ > 0) { + this->num_running_--; + if (this->next_ != nullptr) { + this->next_->play_complex(x...); + } } } virtual void stop() {} virtual void stop_complex() { - this->stop(); + if (num_running_) { + this->stop(); + this->num_running_ = 0; + } this->stop_next(); } void stop_next() { @@ -95,7 +102,7 @@ template class Action { this->next_->stop_complex(); } } - virtual bool is_running() { return this->is_running_next(); } + virtual bool is_running() { return this->num_running_ > 0 || this->is_running_next(); } bool is_running_next() { if (this->next_ == nullptr) return false; @@ -114,6 +121,8 @@ template class Action { } Action *next_ = nullptr; + + int num_running_{0}; }; template class ActionList { diff --git a/esphome/core/base_automation.h b/esphome/core/base_automation.h index add3df0bb5..bd34009790 100644 --- a/esphome/core/base_automation.h +++ b/esphome/core/base_automation.h @@ -110,27 +110,17 @@ template class DelayAction : public Action, public Compon void stop() override { this->cancel_timeout(""); - this->num_running_ = 0; } void play(Ts... x) override { /* ignore - see play_complex */ } void play_complex(Ts... x) override { - auto f = std::bind(&DelayAction::delay_end_, this, x...); + auto f = std::bind(&Action::play_next, this, x...); this->num_running_++; this->set_timeout(this->delay_.value(x...), f); } float get_setup_priority() const override { return setup_priority::HARDWARE; } - - bool is_running() override { return this->num_running_ > 0 || this->is_running_next(); } - - protected: - void delay_end_(Ts... x) { - this->num_running_--; - this->play_next(x...); - } - int num_running_{0}; }; template class LambdaAction : public Action { @@ -160,17 +150,18 @@ template class IfAction : public Action { } void play_complex(Ts... x) override { + this->num_running_++; bool res = this->condition_->check(x...); if (res) { if (this->then_.empty()) { this->play_next(x...); - } else { + } else if (this->num_running_ > 0) { this->then_.play(x...); } } else { if (this->else_.empty()) { this->play_next(x...); - } else { + } else if (this->num_running_ > 0) { this->else_.play(x...); } } @@ -181,8 +172,6 @@ template class IfAction : public Action { this->else_.stop(); } - bool is_running() override { return this->then_.is_running() || this->else_.is_running() || this->is_running_next(); } - protected: Condition *condition_; ActionList then_; @@ -196,9 +185,11 @@ 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->condition_->check_tuple(this->var_)) { + if (this->num_running_ > 0 && this->condition_->check_tuple(this->var_)) { // play again - this->then_.play_tuple(this->var_); + if (this->num_running_ > 0) { + this->then_.play_tuple(this->var_); + } } else { // condition false, play next this->play_next_tuple(this->var_); @@ -210,6 +201,7 @@ template class WhileAction : public Action { } void play_complex(Ts... x) override { + this->num_running_++; // Store loop parameters this->var_ = std::make_tuple(x...); // Initial condition check @@ -220,13 +212,13 @@ template class WhileAction : public Action { return; } - this->then_.play_tuple(this->var_); + if (this->num_running_ > 0) { + this->then_.play_tuple(this->var_); + } } void stop() override { this->then_.stop(); } - bool is_running() override { return this->then_.is_running() || this->is_running_next(); } - protected: Condition *condition_; ActionList then_; @@ -237,42 +229,37 @@ template class WaitUntilAction : public Action, public Co public: WaitUntilAction(Condition *condition) : condition_(condition) {} - void play(Ts... x) { /* ignore - see play_complex */ + void play(Ts... x) override { /* ignore - see play_complex */ } void play_complex(Ts... x) override { + this->num_running_++; // Check if we can continue immediately. if (this->condition_->check(x...)) { - this->triggered_ = false; - this->play_next(x...); + if (this->num_running_ > 0) { + this->play_next(x...); + } return; } this->var_ = std::make_tuple(x...); - this->triggered_ = true; this->loop(); } - void stop() override { this->triggered_ = false; } - void loop() override { - if (!this->triggered_) + if (this->num_running_ == 0) return; if (!this->condition_->check_tuple(this->var_)) { return; } - this->triggered_ = false; this->play_next_tuple(this->var_); } float get_setup_priority() const override { return setup_priority::DATA; } - bool is_running() override { return this->triggered_ || this->is_running_next(); } - protected: Condition *condition_; - bool triggered_{false}; std::tuple var_{}; };