mirror of
https://github.com/esphome/esphome.git
synced 2024-11-10 09:17:46 +01:00
Move stop/is_running implementation to Action base class
Try to fix issue #1105. Until now if an UpdateComponentAction, a LambdaAction, or any action that can contain those inside their "else" or "then" action lists, resulted in a call to script.stop on the script that contains them, the script would continue running, because they didn't implement a stop() method. Basically only the asynchronous ones did: DelayAction, WaitUntilAction and ScriptWaitAction. With this change num_running_ in Action replaces DelayAction::num_running_ and WaitUntilAction::triggered_ to provide the same is_running logic to other actions.
This commit is contained in:
parent
8b92456ded
commit
da390d32f8
3 changed files with 34 additions and 45 deletions
|
@ -53,41 +53,34 @@ template<typename... Ts> class ScriptWaitAction : public Action<Ts...>, 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<Ts...> var_{};
|
||||
};
|
||||
|
||||
|
|
|
@ -77,17 +77,24 @@ template<typename... Ts> 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<typename... Ts> 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<typename... Ts> class Action {
|
|||
}
|
||||
|
||||
Action<Ts...> *next_ = nullptr;
|
||||
|
||||
int num_running_{0};
|
||||
};
|
||||
|
||||
template<typename... Ts> class ActionList {
|
||||
|
|
|
@ -110,27 +110,17 @@ template<typename... Ts> class DelayAction : public Action<Ts...>, 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<Ts...>::delay_end_, this, x...);
|
||||
auto f = std::bind(&Action<Ts...>::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<typename... Ts> class LambdaAction : public Action<Ts...> {
|
||||
|
@ -160,17 +150,18 @@ template<typename... Ts> class IfAction : public Action<Ts...> {
|
|||
}
|
||||
|
||||
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<typename... Ts> class IfAction : public Action<Ts...> {
|
|||
this->else_.stop();
|
||||
}
|
||||
|
||||
bool is_running() override { return this->then_.is_running() || this->else_.is_running() || this->is_running_next(); }
|
||||
|
||||
protected:
|
||||
Condition<Ts...> *condition_;
|
||||
ActionList<Ts...> then_;
|
||||
|
@ -196,9 +185,11 @@ template<typename... Ts> class WhileAction : public Action<Ts...> {
|
|||
void add_then(const std::vector<Action<Ts...> *> &actions) {
|
||||
this->then_.add_actions(actions);
|
||||
this->then_.add_action(new LambdaAction<Ts...>([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<typename... Ts> class WhileAction : public Action<Ts...> {
|
|||
}
|
||||
|
||||
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<typename... Ts> class WhileAction : public Action<Ts...> {
|
|||
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<Ts...> *condition_;
|
||||
ActionList<Ts...> then_;
|
||||
|
@ -237,42 +229,37 @@ template<typename... Ts> class WaitUntilAction : public Action<Ts...>, public Co
|
|||
public:
|
||||
WaitUntilAction(Condition<Ts...> *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<Ts...> *condition_;
|
||||
bool triggered_{false};
|
||||
std::tuple<Ts...> var_{};
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue