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:
|
public:
|
||||||
ScriptWaitAction(Script *script) : script_(script) {}
|
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 {
|
void play_complex(Ts... x) override {
|
||||||
|
this->num_running_++;
|
||||||
// Check if we can continue immediately.
|
// Check if we can continue immediately.
|
||||||
if (!this->script_->is_running()) {
|
if (!this->script_->is_running()) {
|
||||||
this->triggered_ = false;
|
|
||||||
this->play_next(x...);
|
this->play_next(x...);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->var_ = std::make_tuple(x...);
|
this->var_ = std::make_tuple(x...);
|
||||||
this->triggered_ = true;
|
|
||||||
this->loop();
|
this->loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop() override { this->triggered_ = false; }
|
|
||||||
|
|
||||||
void loop() override {
|
void loop() override {
|
||||||
if (!this->triggered_)
|
if (this->num_running_ == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (this->script_->is_running())
|
if (this->script_->is_running())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
this->triggered_ = false;
|
|
||||||
this->play_next_tuple(this->var_);
|
this->play_next_tuple(this->var_);
|
||||||
}
|
}
|
||||||
|
|
||||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||||
|
|
||||||
bool is_running() override { return this->triggered_ || this->is_running_next(); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Script *script_;
|
Script *script_;
|
||||||
bool triggered_{false};
|
|
||||||
std::tuple<Ts...> var_{};
|
std::tuple<Ts...> var_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -77,17 +77,24 @@ template<typename... Ts> class Action {
|
||||||
public:
|
public:
|
||||||
virtual void play(Ts... x) = 0;
|
virtual void play(Ts... x) = 0;
|
||||||
virtual void play_complex(Ts... x) {
|
virtual void play_complex(Ts... x) {
|
||||||
|
this->num_running_++;
|
||||||
this->play(x...);
|
this->play(x...);
|
||||||
this->play_next(x...);
|
this->play_next(x...);
|
||||||
}
|
}
|
||||||
void play_next(Ts... x) {
|
void play_next(Ts... x) {
|
||||||
|
if (this->num_running_ > 0) {
|
||||||
|
this->num_running_--;
|
||||||
if (this->next_ != nullptr) {
|
if (this->next_ != nullptr) {
|
||||||
this->next_->play_complex(x...);
|
this->next_->play_complex(x...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
virtual void stop() {}
|
virtual void stop() {}
|
||||||
virtual void stop_complex() {
|
virtual void stop_complex() {
|
||||||
|
if (num_running_) {
|
||||||
this->stop();
|
this->stop();
|
||||||
|
this->num_running_ = 0;
|
||||||
|
}
|
||||||
this->stop_next();
|
this->stop_next();
|
||||||
}
|
}
|
||||||
void stop_next() {
|
void stop_next() {
|
||||||
|
@ -95,7 +102,7 @@ template<typename... Ts> class Action {
|
||||||
this->next_->stop_complex();
|
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() {
|
bool is_running_next() {
|
||||||
if (this->next_ == nullptr)
|
if (this->next_ == nullptr)
|
||||||
return false;
|
return false;
|
||||||
|
@ -114,6 +121,8 @@ template<typename... Ts> class Action {
|
||||||
}
|
}
|
||||||
|
|
||||||
Action<Ts...> *next_ = nullptr;
|
Action<Ts...> *next_ = nullptr;
|
||||||
|
|
||||||
|
int num_running_{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Ts> class ActionList {
|
template<typename... Ts> class ActionList {
|
||||||
|
|
|
@ -110,27 +110,17 @@ template<typename... Ts> class DelayAction : public Action<Ts...>, public Compon
|
||||||
|
|
||||||
void stop() override {
|
void stop() override {
|
||||||
this->cancel_timeout("");
|
this->cancel_timeout("");
|
||||||
this->num_running_ = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void play(Ts... x) override { /* ignore - see play_complex */
|
void play(Ts... x) override { /* ignore - see play_complex */
|
||||||
}
|
}
|
||||||
|
|
||||||
void play_complex(Ts... x) override {
|
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->num_running_++;
|
||||||
this->set_timeout(this->delay_.value(x...), f);
|
this->set_timeout(this->delay_.value(x...), f);
|
||||||
}
|
}
|
||||||
float get_setup_priority() const override { return setup_priority::HARDWARE; }
|
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...> {
|
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 {
|
void play_complex(Ts... x) override {
|
||||||
|
this->num_running_++;
|
||||||
bool res = this->condition_->check(x...);
|
bool res = this->condition_->check(x...);
|
||||||
if (res) {
|
if (res) {
|
||||||
if (this->then_.empty()) {
|
if (this->then_.empty()) {
|
||||||
this->play_next(x...);
|
this->play_next(x...);
|
||||||
} else {
|
} else if (this->num_running_ > 0) {
|
||||||
this->then_.play(x...);
|
this->then_.play(x...);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (this->else_.empty()) {
|
if (this->else_.empty()) {
|
||||||
this->play_next(x...);
|
this->play_next(x...);
|
||||||
} else {
|
} else if (this->num_running_ > 0) {
|
||||||
this->else_.play(x...);
|
this->else_.play(x...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -181,8 +172,6 @@ template<typename... Ts> class IfAction : public Action<Ts...> {
|
||||||
this->else_.stop();
|
this->else_.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_running() override { return this->then_.is_running() || this->else_.is_running() || this->is_running_next(); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Condition<Ts...> *condition_;
|
Condition<Ts...> *condition_;
|
||||||
ActionList<Ts...> then_;
|
ActionList<Ts...> then_;
|
||||||
|
@ -196,9 +185,11 @@ template<typename... Ts> class WhileAction : public Action<Ts...> {
|
||||||
void add_then(const std::vector<Action<Ts...> *> &actions) {
|
void add_then(const std::vector<Action<Ts...> *> &actions) {
|
||||||
this->then_.add_actions(actions);
|
this->then_.add_actions(actions);
|
||||||
this->then_.add_action(new LambdaAction<Ts...>([this](Ts... x) {
|
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
|
// play again
|
||||||
|
if (this->num_running_ > 0) {
|
||||||
this->then_.play_tuple(this->var_);
|
this->then_.play_tuple(this->var_);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// condition false, play next
|
// condition false, play next
|
||||||
this->play_next_tuple(this->var_);
|
this->play_next_tuple(this->var_);
|
||||||
|
@ -210,6 +201,7 @@ template<typename... Ts> class WhileAction : public Action<Ts...> {
|
||||||
}
|
}
|
||||||
|
|
||||||
void play_complex(Ts... x) override {
|
void play_complex(Ts... x) override {
|
||||||
|
this->num_running_++;
|
||||||
// Store loop parameters
|
// Store loop parameters
|
||||||
this->var_ = std::make_tuple(x...);
|
this->var_ = std::make_tuple(x...);
|
||||||
// Initial condition check
|
// Initial condition check
|
||||||
|
@ -220,13 +212,13 @@ template<typename... Ts> class WhileAction : public Action<Ts...> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this->num_running_ > 0) {
|
||||||
this->then_.play_tuple(this->var_);
|
this->then_.play_tuple(this->var_);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void stop() override { this->then_.stop(); }
|
void stop() override { this->then_.stop(); }
|
||||||
|
|
||||||
bool is_running() override { return this->then_.is_running() || this->is_running_next(); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Condition<Ts...> *condition_;
|
Condition<Ts...> *condition_;
|
||||||
ActionList<Ts...> then_;
|
ActionList<Ts...> then_;
|
||||||
|
@ -237,42 +229,37 @@ template<typename... Ts> class WaitUntilAction : public Action<Ts...>, public Co
|
||||||
public:
|
public:
|
||||||
WaitUntilAction(Condition<Ts...> *condition) : condition_(condition) {}
|
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 {
|
void play_complex(Ts... x) override {
|
||||||
|
this->num_running_++;
|
||||||
// Check if we can continue immediately.
|
// Check if we can continue immediately.
|
||||||
if (this->condition_->check(x...)) {
|
if (this->condition_->check(x...)) {
|
||||||
this->triggered_ = false;
|
if (this->num_running_ > 0) {
|
||||||
this->play_next(x...);
|
this->play_next(x...);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->var_ = std::make_tuple(x...);
|
this->var_ = std::make_tuple(x...);
|
||||||
this->triggered_ = true;
|
|
||||||
this->loop();
|
this->loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop() override { this->triggered_ = false; }
|
|
||||||
|
|
||||||
void loop() override {
|
void loop() override {
|
||||||
if (!this->triggered_)
|
if (this->num_running_ == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!this->condition_->check_tuple(this->var_)) {
|
if (!this->condition_->check_tuple(this->var_)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->triggered_ = false;
|
|
||||||
this->play_next_tuple(this->var_);
|
this->play_next_tuple(this->var_);
|
||||||
}
|
}
|
||||||
|
|
||||||
float get_setup_priority() const override { return setup_priority::DATA; }
|
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||||
|
|
||||||
bool is_running() override { return this->triggered_ || this->is_running_next(); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Condition<Ts...> *condition_;
|
Condition<Ts...> *condition_;
|
||||||
bool triggered_{false};
|
|
||||||
std::tuple<Ts...> var_{};
|
std::tuple<Ts...> var_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue