mirror of
https://github.com/esphome/esphome.git
synced 2025-03-15 15:18:16 +00:00
actions: fix loop re-entry
This commit is contained in:
parent
54fbf5184e
commit
f846bcbe87
@ -225,7 +225,7 @@ template<class C, typename... Ts> class ScriptWaitAction : public Action<Ts...>,
|
|||||||
this->play_next_(x...);
|
this->play_next_(x...);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->var_ = std::make_tuple(x...);
|
this->play_queue_.push([this, x...]() { this->play_next_(x...); });
|
||||||
this->loop();
|
this->loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -236,7 +236,11 @@ template<class C, typename... Ts> class ScriptWaitAction : public Action<Ts...>,
|
|||||||
if (this->script_->is_running())
|
if (this->script_->is_running())
|
||||||
return;
|
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; }
|
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||||
@ -246,7 +250,7 @@ template<class C, typename... Ts> class ScriptWaitAction : public Action<Ts...>,
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
C *script_;
|
C *script_;
|
||||||
std::tuple<Ts...> var_{};
|
std::queue<std::function<void()>> play_queue_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace script
|
} // namespace script
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "esphome/core/preferences.h"
|
#include "esphome/core/preferences.h"
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
|
|
||||||
@ -230,32 +231,30 @@ 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->num_running_ > 0 && this->condition_->check_tuple(this->var_)) {
|
if (this->num_running_ > 0 && this->condition_->check(x...)) {
|
||||||
// play again
|
// play again
|
||||||
if (this->num_running_ > 0) {
|
if (this->num_running_ > 0) {
|
||||||
this->then_.play_tuple(this->var_);
|
this->then_.play(x...);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// condition false, play next
|
// condition false, play next
|
||||||
this->play_next_tuple_(this->var_);
|
this->play_next_(x...);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
void play_complex(Ts... x) override {
|
void play_complex(Ts... x) override {
|
||||||
this->num_running_++;
|
this->num_running_++;
|
||||||
// Store loop parameters
|
|
||||||
this->var_ = std::make_tuple(x...);
|
|
||||||
// Initial condition check
|
// Initial condition check
|
||||||
if (!this->condition_->check_tuple(this->var_)) {
|
if (!this->condition_->check(x...)) {
|
||||||
// If new condition check failed, stop loop if running
|
// If new condition check failed, stop loop if running
|
||||||
this->then_.stop();
|
this->then_.stop();
|
||||||
this->play_next_tuple_(this->var_);
|
this->play_next_(x...);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->num_running_ > 0) {
|
if (this->num_running_ > 0) {
|
||||||
this->then_.play_tuple(this->var_);
|
this->then_.play(x...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -267,7 +266,6 @@ template<typename... Ts> class WhileAction : public Action<Ts...> {
|
|||||||
protected:
|
protected:
|
||||||
Condition<Ts...> *condition_;
|
Condition<Ts...> *condition_;
|
||||||
ActionList<Ts...> then_;
|
ActionList<Ts...> then_;
|
||||||
std::tuple<Ts...> var_{};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Ts> class RepeatAction : public Action<Ts...> {
|
template<typename... Ts> class RepeatAction : public Action<Ts...> {
|
||||||
@ -279,7 +277,7 @@ template<typename... Ts> class RepeatAction : public Action<Ts...> {
|
|||||||
this->then_.add_action(new LambdaAction<uint32_t, Ts...>([this](uint32_t iteration, Ts... x) {
|
this->then_.add_action(new LambdaAction<uint32_t, Ts...>([this](uint32_t iteration, Ts... x) {
|
||||||
iteration++;
|
iteration++;
|
||||||
if (iteration >= this->count_.value(x...)) {
|
if (iteration >= this->count_.value(x...)) {
|
||||||
this->play_next_tuple_(this->var_);
|
this->play_next_(x...);
|
||||||
} else {
|
} else {
|
||||||
this->then_.play(iteration, x...);
|
this->then_.play(iteration, x...);
|
||||||
}
|
}
|
||||||
@ -288,11 +286,10 @@ template<typename... Ts> class RepeatAction : public Action<Ts...> {
|
|||||||
|
|
||||||
void play_complex(Ts... x) override {
|
void play_complex(Ts... x) override {
|
||||||
this->num_running_++;
|
this->num_running_++;
|
||||||
this->var_ = std::make_tuple(x...);
|
|
||||||
if (this->count_.value(x...) > 0) {
|
if (this->count_.value(x...) > 0) {
|
||||||
this->then_.play(0, x...);
|
this->then_.play(0, x...);
|
||||||
} else {
|
} else {
|
||||||
this->play_next_tuple_(this->var_);
|
this->play_next_(x...);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -303,7 +300,6 @@ template<typename... Ts> class RepeatAction : public Action<Ts...> {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
ActionList<uint32_t, Ts...> then_;
|
ActionList<uint32_t, Ts...> then_;
|
||||||
std::tuple<Ts...> var_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Ts> class WaitUntilAction : public Action<Ts...>, public Component {
|
template<typename... Ts> class WaitUntilAction : public Action<Ts...>, public Component {
|
||||||
@ -321,12 +317,11 @@ template<typename... Ts> class WaitUntilAction : public Action<Ts...>, public Co
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this->var_ = std::make_tuple(x...);
|
|
||||||
|
|
||||||
if (this->timeout_value_.has_value()) {
|
auto now = millis();
|
||||||
auto f = std::bind(&WaitUntilAction<Ts...>::play_next_, this, x...);
|
auto timeout = this->timeout_value_.optional_value(x...);
|
||||||
this->set_timeout("timeout", this->timeout_value_.value(x...), f);
|
|
||||||
}
|
this->var_queue_.emplace_front(now, timeout, std::make_tuple(x...));
|
||||||
|
|
||||||
this->loop();
|
this->loop();
|
||||||
}
|
}
|
||||||
@ -335,13 +330,22 @@ template<typename... Ts> class WaitUntilAction : public Action<Ts...>, public Co
|
|||||||
if (this->num_running_ == 0)
|
if (this->num_running_ == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!this->condition_->check_tuple(this->var_)) {
|
auto now = millis();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->cancel_timeout("timeout");
|
this->var_queue_.remove_if([&](decltype(*this->var_queue_.cbegin()) &queued) {
|
||||||
|
auto start = std::get<uint32_t>(queued);
|
||||||
|
auto timeout = std::get<optional<uint32_t>>(queued);
|
||||||
|
auto var = std::get<std::tuple<Ts...>>(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; }
|
float get_setup_priority() const override { return setup_priority::DATA; }
|
||||||
@ -349,11 +353,11 @@ template<typename... Ts> class WaitUntilAction : public Action<Ts...>, public Co
|
|||||||
void play(Ts... x) override { /* ignore - see play_complex */
|
void play(Ts... x) override { /* ignore - see play_complex */
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop() override { this->cancel_timeout("timeout"); }
|
void stop() override { this->var_queue_.clear(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Condition<Ts...> *condition_;
|
Condition<Ts...> *condition_;
|
||||||
std::tuple<Ts...> var_{};
|
std::list<std::tuple<uint32_t, optional<uint32_t>, std::tuple<Ts...>>> var_queue_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename... Ts> class UpdateComponentAction : public Action<Ts...> {
|
template<typename... Ts> class UpdateComponentAction : public Action<Ts...> {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user