[binary_sensor] Drop Component from AutorepeatFilter, use self-keyed scheduler (#16191)
This commit is contained in:
1 parent
9ddb828da3
commit
013dee44eb
5 files changed
+177
-19
No files matched your search
@@ -148,7 +148,7 @@ DelayedOnOffFilter = binary_sensor_ns.class_("DelayedOnOffFilter", Filter)
|
||||
DelayedOnFilter = binary_sensor_ns.class_("DelayedOnFilter", Filter)
|
||||
DelayedOffFilter = binary_sensor_ns.class_("DelayedOffFilter", Filter)
|
||||
InvertFilter = binary_sensor_ns.class_("InvertFilter", Filter)
|
||||
AutorepeatFilter = binary_sensor_ns.class_("AutorepeatFilter", Filter, cg.Component)
|
||||
AutorepeatFilter = binary_sensor_ns.class_("AutorepeatFilter", Filter)
|
||||
LambdaFilter = binary_sensor_ns.class_("LambdaFilter", Filter)
|
||||
StatelessLambdaFilter = binary_sensor_ns.class_("StatelessLambdaFilter", Filter)
|
||||
SettleFilter = binary_sensor_ns.class_("SettleFilter", Filter)
|
||||
@@ -282,9 +282,7 @@ async def autorepeat_filter_to_code(config, filter_id):
|
||||
),
|
||||
)
|
||||
]
|
||||
var = cg.new_Pvariable(filter_id, cg.TemplateArguments(len(timings)), timings)
|
||||
await cg.register_component(var, {})
|
||||
return var
|
||||
return cg.new_Pvariable(filter_id, cg.TemplateArguments(len(timings)), timings)
|
||||
|
||||
|
||||
@register_filter("lambda", LambdaFilter, cv.returning_lambda)
|
||||
|
||||
@@ -10,11 +10,6 @@ namespace esphome::binary_sensor {
|
||||
|
||||
static const char *const TAG = "sensor.filter";
|
||||
|
||||
// AutorepeatFilter still inherits Component (it schedules two distinct timer
|
||||
// purposes), so it keeps the (Component *, id) scheduler API.
|
||||
constexpr uint32_t AUTOREPEAT_TIMING_ID = 0;
|
||||
constexpr uint32_t AUTOREPEAT_ON_OFF_ID = 1;
|
||||
|
||||
void Filter::output(bool value) {
|
||||
if (this->next_ == nullptr) {
|
||||
this->parent_->send_state_internal(value);
|
||||
@@ -69,6 +64,10 @@ optional<bool> DelayedOffFilter::new_value(bool value) {
|
||||
optional<bool> InvertFilter::new_value(bool value) { return !value; }
|
||||
|
||||
// AutorepeatFilterBase
|
||||
// Two independent timers per instance, keyed off two stable addresses inside
|
||||
// the filter: `this` for the timing-step timer, `&active_timing_` for the
|
||||
// on/off timer. Both are unique per instance and don't collide with anything
|
||||
// else, so the self-keyed scheduler API is sufficient.
|
||||
optional<bool> AutorepeatFilterBase::new_value(bool value) {
|
||||
if (value) {
|
||||
if (this->active_timing_ != 0)
|
||||
@@ -76,8 +75,8 @@ optional<bool> AutorepeatFilterBase::new_value(bool value) {
|
||||
this->next_timing_();
|
||||
return true;
|
||||
} else {
|
||||
this->cancel_timeout(AUTOREPEAT_TIMING_ID);
|
||||
this->cancel_timeout(AUTOREPEAT_ON_OFF_ID);
|
||||
App.scheduler.cancel_timeout(this);
|
||||
App.scheduler.cancel_timeout(&this->active_timing_);
|
||||
this->active_timing_ = 0;
|
||||
return false;
|
||||
}
|
||||
@@ -85,8 +84,7 @@ optional<bool> AutorepeatFilterBase::new_value(bool value) {
|
||||
|
||||
void AutorepeatFilterBase::next_timing_() {
|
||||
if (this->active_timing_ < this->timings_count_) {
|
||||
this->set_timeout(AUTOREPEAT_TIMING_ID, this->timings_[this->active_timing_].delay,
|
||||
[this]() { this->next_timing_(); });
|
||||
App.scheduler.set_timeout(this, this->timings_[this->active_timing_].delay, [this]() { this->next_timing_(); });
|
||||
}
|
||||
if (this->active_timing_ <= this->timings_count_) {
|
||||
this->active_timing_++;
|
||||
@@ -98,12 +96,10 @@ void AutorepeatFilterBase::next_timing_() {
|
||||
void AutorepeatFilterBase::next_value_(bool val) {
|
||||
const AutorepeatFilterTiming &timing = this->timings_[this->active_timing_ - 2];
|
||||
this->output(val);
|
||||
this->set_timeout(AUTOREPEAT_ON_OFF_ID, val ? timing.time_on : timing.time_off,
|
||||
[this, val]() { this->next_value_(!val); });
|
||||
App.scheduler.set_timeout(&this->active_timing_, val ? timing.time_on : timing.time_off,
|
||||
[this, val]() { this->next_value_(!val); });
|
||||
}
|
||||
|
||||
float AutorepeatFilterBase::get_setup_priority() const { return setup_priority::HARDWARE; }
|
||||
|
||||
LambdaFilter::LambdaFilter(std::function<optional<bool>(bool)> f) : f_(std::move(f)) {}
|
||||
|
||||
optional<bool> LambdaFilter::new_value(bool value) { return this->f_(value); }
|
||||
|
||||
@@ -84,10 +84,11 @@ struct AutorepeatFilterTiming {
|
||||
|
||||
/// Non-template base for AutorepeatFilter — all methods in filter.cpp.
|
||||
/// Lambdas capture this base pointer, so set_timeout/cancel_timeout are instantiated once.
|
||||
class AutorepeatFilterBase : public Filter, public Component {
|
||||
/// The two scheduled timers are keyed off `this` and `&active_timing_`; since the address
|
||||
/// of `active_timing_` is taken as a scheduler key, the class must not be copied or moved.
|
||||
class AutorepeatFilterBase : public Filter {
|
||||
public:
|
||||
optional<bool> new_value(bool value) override;
|
||||
float get_setup_priority() const override;
|
||||
AutorepeatFilterBase(const AutorepeatFilterBase &) = delete;
|
||||
AutorepeatFilterBase &operator=(const AutorepeatFilterBase &) = delete;
|
||||
|
||||
|
||||
Reference in new issue
Block a user