mirror of
https://github.com/esphome/esphome.git
synced 2026-06-02 03:02:19 +08:00
[binary_sensor] Drop Component from filter classes, use self-keyed scheduler (#16131)
This commit is contained in:
@@ -143,15 +143,15 @@ BinarySensorCondition = binary_sensor_ns.class_("BinarySensorCondition", Conditi
|
|||||||
|
|
||||||
# Filters
|
# Filters
|
||||||
Filter = binary_sensor_ns.class_("Filter")
|
Filter = binary_sensor_ns.class_("Filter")
|
||||||
TimeoutFilter = binary_sensor_ns.class_("TimeoutFilter", Filter, cg.Component)
|
TimeoutFilter = binary_sensor_ns.class_("TimeoutFilter", Filter)
|
||||||
DelayedOnOffFilter = binary_sensor_ns.class_("DelayedOnOffFilter", Filter, cg.Component)
|
DelayedOnOffFilter = binary_sensor_ns.class_("DelayedOnOffFilter", Filter)
|
||||||
DelayedOnFilter = binary_sensor_ns.class_("DelayedOnFilter", Filter, cg.Component)
|
DelayedOnFilter = binary_sensor_ns.class_("DelayedOnFilter", Filter)
|
||||||
DelayedOffFilter = binary_sensor_ns.class_("DelayedOffFilter", Filter, cg.Component)
|
DelayedOffFilter = binary_sensor_ns.class_("DelayedOffFilter", Filter)
|
||||||
InvertFilter = binary_sensor_ns.class_("InvertFilter", Filter)
|
InvertFilter = binary_sensor_ns.class_("InvertFilter", Filter)
|
||||||
AutorepeatFilter = binary_sensor_ns.class_("AutorepeatFilter", Filter, cg.Component)
|
AutorepeatFilter = binary_sensor_ns.class_("AutorepeatFilter", Filter, cg.Component)
|
||||||
LambdaFilter = binary_sensor_ns.class_("LambdaFilter", Filter)
|
LambdaFilter = binary_sensor_ns.class_("LambdaFilter", Filter)
|
||||||
StatelessLambdaFilter = binary_sensor_ns.class_("StatelessLambdaFilter", Filter)
|
StatelessLambdaFilter = binary_sensor_ns.class_("StatelessLambdaFilter", Filter)
|
||||||
SettleFilter = binary_sensor_ns.class_("SettleFilter", Filter, cg.Component)
|
SettleFilter = binary_sensor_ns.class_("SettleFilter", Filter)
|
||||||
|
|
||||||
_LOGGER = getLogger(__name__)
|
_LOGGER = getLogger(__name__)
|
||||||
|
|
||||||
@@ -175,7 +175,6 @@ async def invert_filter_to_code(config, filter_id):
|
|||||||
)
|
)
|
||||||
async def timeout_filter_to_code(config, filter_id):
|
async def timeout_filter_to_code(config, filter_id):
|
||||||
var = cg.new_Pvariable(filter_id)
|
var = cg.new_Pvariable(filter_id)
|
||||||
await cg.register_component(var, {})
|
|
||||||
template_ = await cg.templatable(config, [], cg.uint32)
|
template_ = await cg.templatable(config, [], cg.uint32)
|
||||||
cg.add(var.set_timeout_value(template_))
|
cg.add(var.set_timeout_value(template_))
|
||||||
return var
|
return var
|
||||||
@@ -203,7 +202,6 @@ async def timeout_filter_to_code(config, filter_id):
|
|||||||
)
|
)
|
||||||
async def delayed_on_off_filter_to_code(config, filter_id):
|
async def delayed_on_off_filter_to_code(config, filter_id):
|
||||||
var = cg.new_Pvariable(filter_id)
|
var = cg.new_Pvariable(filter_id)
|
||||||
await cg.register_component(var, {})
|
|
||||||
if isinstance(config, dict):
|
if isinstance(config, dict):
|
||||||
template_ = await cg.templatable(config[CONF_TIME_ON], [], cg.uint32)
|
template_ = await cg.templatable(config[CONF_TIME_ON], [], cg.uint32)
|
||||||
cg.add(var.set_on_delay(template_))
|
cg.add(var.set_on_delay(template_))
|
||||||
@@ -221,7 +219,6 @@ async def delayed_on_off_filter_to_code(config, filter_id):
|
|||||||
)
|
)
|
||||||
async def delayed_on_filter_to_code(config, filter_id):
|
async def delayed_on_filter_to_code(config, filter_id):
|
||||||
var = cg.new_Pvariable(filter_id)
|
var = cg.new_Pvariable(filter_id)
|
||||||
await cg.register_component(var, {})
|
|
||||||
template_ = await cg.templatable(config, [], cg.uint32)
|
template_ = await cg.templatable(config, [], cg.uint32)
|
||||||
cg.add(var.set_delay(template_))
|
cg.add(var.set_delay(template_))
|
||||||
return var
|
return var
|
||||||
@@ -234,7 +231,6 @@ async def delayed_on_filter_to_code(config, filter_id):
|
|||||||
)
|
)
|
||||||
async def delayed_off_filter_to_code(config, filter_id):
|
async def delayed_off_filter_to_code(config, filter_id):
|
||||||
var = cg.new_Pvariable(filter_id)
|
var = cg.new_Pvariable(filter_id)
|
||||||
await cg.register_component(var, {})
|
|
||||||
template_ = await cg.templatable(config, [], cg.uint32)
|
template_ = await cg.templatable(config, [], cg.uint32)
|
||||||
cg.add(var.set_delay(template_))
|
cg.add(var.set_delay(template_))
|
||||||
return var
|
return var
|
||||||
@@ -306,7 +302,6 @@ async def lambda_filter_to_code(config, filter_id):
|
|||||||
)
|
)
|
||||||
async def settle_filter_to_code(config, filter_id):
|
async def settle_filter_to_code(config, filter_id):
|
||||||
var = cg.new_Pvariable(filter_id)
|
var = cg.new_Pvariable(filter_id)
|
||||||
await cg.register_component(var, {})
|
|
||||||
template_ = await cg.templatable(config, [], cg.uint32)
|
template_ = await cg.templatable(config, [], cg.uint32)
|
||||||
cg.add(var.set_delay(template_))
|
cg.add(var.set_delay(template_))
|
||||||
return var
|
return var
|
||||||
|
|||||||
@@ -4,16 +4,14 @@
|
|||||||
#include "filter.h"
|
#include "filter.h"
|
||||||
|
|
||||||
#include "binary_sensor.h"
|
#include "binary_sensor.h"
|
||||||
|
#include "esphome/core/application.h"
|
||||||
|
|
||||||
namespace esphome::binary_sensor {
|
namespace esphome::binary_sensor {
|
||||||
|
|
||||||
static const char *const TAG = "sensor.filter";
|
static const char *const TAG = "sensor.filter";
|
||||||
|
|
||||||
// Timeout IDs for filter classes.
|
// AutorepeatFilter still inherits Component (it schedules two distinct timer
|
||||||
// Each filter is its own Component instance, so the scheduler scopes
|
// purposes), so it keeps the (Component *, id) scheduler API.
|
||||||
// IDs by component pointer — no risk of collisions between instances.
|
|
||||||
constexpr uint32_t FILTER_TIMEOUT_ID = 0;
|
|
||||||
// AutorepeatFilter needs two distinct IDs (both timeouts on the same component)
|
|
||||||
constexpr uint32_t AUTOREPEAT_TIMING_ID = 0;
|
constexpr uint32_t AUTOREPEAT_TIMING_ID = 0;
|
||||||
constexpr uint32_t AUTOREPEAT_ON_OFF_ID = 1;
|
constexpr uint32_t AUTOREPEAT_ON_OFF_ID = 1;
|
||||||
|
|
||||||
@@ -34,46 +32,40 @@ void Filter::input(bool value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void TimeoutFilter::input(bool value) {
|
void TimeoutFilter::input(bool value) {
|
||||||
this->set_timeout(FILTER_TIMEOUT_ID, this->timeout_delay_.value(), [this]() { this->parent_->invalidate_state(); });
|
App.scheduler.set_timeout(this, this->timeout_delay_.value(), [this]() { this->parent_->invalidate_state(); });
|
||||||
// we do not de-dup here otherwise changes from invalid to valid state will not be output
|
// we do not de-dup here otherwise changes from invalid to valid state will not be output
|
||||||
this->output(value);
|
this->output(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<bool> DelayedOnOffFilter::new_value(bool value) {
|
optional<bool> DelayedOnOffFilter::new_value(bool value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
this->set_timeout(FILTER_TIMEOUT_ID, this->on_delay_.value(), [this]() { this->output(true); });
|
App.scheduler.set_timeout(this, this->on_delay_.value(), [this]() { this->output(true); });
|
||||||
} else {
|
} else {
|
||||||
this->set_timeout(FILTER_TIMEOUT_ID, this->off_delay_.value(), [this]() { this->output(false); });
|
App.scheduler.set_timeout(this, this->off_delay_.value(), [this]() { this->output(false); });
|
||||||
}
|
}
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
float DelayedOnOffFilter::get_setup_priority() const { return setup_priority::HARDWARE; }
|
|
||||||
|
|
||||||
optional<bool> DelayedOnFilter::new_value(bool value) {
|
optional<bool> DelayedOnFilter::new_value(bool value) {
|
||||||
if (value) {
|
if (value) {
|
||||||
this->set_timeout(FILTER_TIMEOUT_ID, this->delay_.value(), [this]() { this->output(true); });
|
App.scheduler.set_timeout(this, this->delay_.value(), [this]() { this->output(true); });
|
||||||
return {};
|
return {};
|
||||||
} else {
|
} else {
|
||||||
this->cancel_timeout(FILTER_TIMEOUT_ID);
|
App.scheduler.cancel_timeout(this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float DelayedOnFilter::get_setup_priority() const { return setup_priority::HARDWARE; }
|
|
||||||
|
|
||||||
optional<bool> DelayedOffFilter::new_value(bool value) {
|
optional<bool> DelayedOffFilter::new_value(bool value) {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
this->set_timeout(FILTER_TIMEOUT_ID, this->delay_.value(), [this]() { this->output(false); });
|
App.scheduler.set_timeout(this, this->delay_.value(), [this]() { this->output(false); });
|
||||||
return {};
|
return {};
|
||||||
} else {
|
} else {
|
||||||
this->cancel_timeout(FILTER_TIMEOUT_ID);
|
App.scheduler.cancel_timeout(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float DelayedOffFilter::get_setup_priority() const { return setup_priority::HARDWARE; }
|
|
||||||
|
|
||||||
optional<bool> InvertFilter::new_value(bool value) { return !value; }
|
optional<bool> InvertFilter::new_value(bool value) { return !value; }
|
||||||
|
|
||||||
// AutorepeatFilterBase
|
// AutorepeatFilterBase
|
||||||
@@ -118,20 +110,18 @@ optional<bool> LambdaFilter::new_value(bool value) { return this->f_(value); }
|
|||||||
|
|
||||||
optional<bool> SettleFilter::new_value(bool value) {
|
optional<bool> SettleFilter::new_value(bool value) {
|
||||||
if (!this->steady_) {
|
if (!this->steady_) {
|
||||||
this->set_timeout(FILTER_TIMEOUT_ID, this->delay_.value(), [this, value]() {
|
App.scheduler.set_timeout(this, this->delay_.value(), [this, value]() {
|
||||||
this->steady_ = true;
|
this->steady_ = true;
|
||||||
this->output(value);
|
this->output(value);
|
||||||
});
|
});
|
||||||
return {};
|
return {};
|
||||||
} else {
|
} else {
|
||||||
this->steady_ = false;
|
this->steady_ = false;
|
||||||
this->set_timeout(FILTER_TIMEOUT_ID, this->delay_.value(), [this]() { this->steady_ = true; });
|
App.scheduler.set_timeout(this, this->delay_.value(), [this]() { this->steady_ = true; });
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float SettleFilter::get_setup_priority() const { return setup_priority::HARDWARE; }
|
|
||||||
|
|
||||||
} // namespace esphome::binary_sensor
|
} // namespace esphome::binary_sensor
|
||||||
|
|
||||||
#endif // USE_BINARY_SENSOR_FILTER
|
#endif // USE_BINARY_SENSOR_FILTER
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ class Filter {
|
|||||||
Deduplicator<bool> dedup_;
|
Deduplicator<bool> dedup_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TimeoutFilter : public Filter, public Component {
|
class TimeoutFilter : public Filter {
|
||||||
public:
|
public:
|
||||||
optional<bool> new_value(bool value) override { return value; }
|
optional<bool> new_value(bool value) override { return value; }
|
||||||
void input(bool value) override;
|
void input(bool value) override;
|
||||||
@@ -39,12 +39,10 @@ class TimeoutFilter : public Filter, public Component {
|
|||||||
TemplatableFn<uint32_t> timeout_delay_{};
|
TemplatableFn<uint32_t> timeout_delay_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class DelayedOnOffFilter final : public Filter, public Component {
|
class DelayedOnOffFilter final : public Filter {
|
||||||
public:
|
public:
|
||||||
optional<bool> new_value(bool value) override;
|
optional<bool> new_value(bool value) override;
|
||||||
|
|
||||||
float get_setup_priority() const override;
|
|
||||||
|
|
||||||
template<typename T> void set_on_delay(T delay) { this->on_delay_ = delay; }
|
template<typename T> void set_on_delay(T delay) { this->on_delay_ = delay; }
|
||||||
template<typename T> void set_off_delay(T delay) { this->off_delay_ = delay; }
|
template<typename T> void set_off_delay(T delay) { this->off_delay_ = delay; }
|
||||||
|
|
||||||
@@ -53,24 +51,20 @@ class DelayedOnOffFilter final : public Filter, public Component {
|
|||||||
TemplatableFn<uint32_t> off_delay_{};
|
TemplatableFn<uint32_t> off_delay_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class DelayedOnFilter : public Filter, public Component {
|
class DelayedOnFilter : public Filter {
|
||||||
public:
|
public:
|
||||||
optional<bool> new_value(bool value) override;
|
optional<bool> new_value(bool value) override;
|
||||||
|
|
||||||
float get_setup_priority() const override;
|
|
||||||
|
|
||||||
template<typename T> void set_delay(T delay) { this->delay_ = delay; }
|
template<typename T> void set_delay(T delay) { this->delay_ = delay; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TemplatableFn<uint32_t> delay_{};
|
TemplatableFn<uint32_t> delay_{};
|
||||||
};
|
};
|
||||||
|
|
||||||
class DelayedOffFilter : public Filter, public Component {
|
class DelayedOffFilter : public Filter {
|
||||||
public:
|
public:
|
||||||
optional<bool> new_value(bool value) override;
|
optional<bool> new_value(bool value) override;
|
||||||
|
|
||||||
float get_setup_priority() const override;
|
|
||||||
|
|
||||||
template<typename T> void set_delay(T delay) { this->delay_ = delay; }
|
template<typename T> void set_delay(T delay) { this->delay_ = delay; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -146,12 +140,10 @@ class StatelessLambdaFilter : public Filter {
|
|||||||
optional<bool> (*f_)(bool);
|
optional<bool> (*f_)(bool);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SettleFilter : public Filter, public Component {
|
class SettleFilter : public Filter {
|
||||||
public:
|
public:
|
||||||
optional<bool> new_value(bool value) override;
|
optional<bool> new_value(bool value) override;
|
||||||
|
|
||||||
float get_setup_priority() const override;
|
|
||||||
|
|
||||||
template<typename T> void set_delay(T delay) { this->delay_ = delay; }
|
template<typename T> void set_delay(T delay) { this->delay_ = delay; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
Reference in New Issue
Block a user