[binary_sensor] Add timeout filter (#9198)

This commit is contained in:
Clyde Stubbs 2025-06-25 22:09:43 +10:00 committed by GitHub
parent b18ff48b4a
commit f35be6b5cc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 56 additions and 1 deletions

View File

@ -148,6 +148,7 @@ BinarySensorCondition = binary_sensor_ns.class_("BinarySensorCondition", Conditi
# Filters
Filter = binary_sensor_ns.class_("Filter")
TimeoutFilter = binary_sensor_ns.class_("TimeoutFilter", Filter, cg.Component)
DelayedOnOffFilter = binary_sensor_ns.class_("DelayedOnOffFilter", Filter, cg.Component)
DelayedOnFilter = binary_sensor_ns.class_("DelayedOnFilter", Filter, cg.Component)
DelayedOffFilter = binary_sensor_ns.class_("DelayedOffFilter", Filter, cg.Component)
@ -171,6 +172,19 @@ async def invert_filter_to_code(config, filter_id):
return cg.new_Pvariable(filter_id)
@register_filter(
"timeout",
TimeoutFilter,
cv.templatable(cv.positive_time_period_milliseconds),
)
async def timeout_filter_to_code(config, filter_id):
var = cg.new_Pvariable(filter_id)
await cg.register_component(var, {})
template_ = await cg.templatable(config, [], cg.uint32)
cg.add(var.set_timeout_value(template_))
return var
@register_filter(
"delayed_on_off",
DelayedOnOffFilter,

View File

@ -25,6 +25,12 @@ void Filter::input(bool value) {
}
}
void TimeoutFilter::input(bool value) {
this->set_timeout("timeout", 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
this->output(value);
}
optional<bool> DelayedOnOffFilter::new_value(bool value) {
if (value) {
this->set_timeout("ON_OFF", this->on_delay_.value(), [this]() { this->output(true); });

View File

@ -16,7 +16,7 @@ class Filter {
public:
virtual optional<bool> new_value(bool value) = 0;
void input(bool value);
virtual void input(bool value);
void output(bool value);
@ -28,6 +28,16 @@ class Filter {
Deduplicator<bool> dedup_;
};
class TimeoutFilter : public Filter, public Component {
public:
optional<bool> new_value(bool value) override { return value; }
void input(bool value) override;
template<typename T> void set_timeout_value(T timeout) { this->timeout_delay_ = timeout; }
protected:
TemplatableValue<uint32_t> timeout_delay_{};
};
class DelayedOnOffFilter : public Filter, public Component {
public:
optional<bool> new_value(bool value) override;

View File

@ -4,6 +4,31 @@ binary_sensor:
id: some_binary_sensor
name: "Random binary"
lambda: return (random_uint32() & 1) == 0;
filters:
- invert:
- delayed_on: 100ms
- delayed_off: 100ms
# Templated, delays for 1s (1000ms) only if a reed switch is active
- delayed_on_off: !lambda "return 1000;"
- delayed_on_off:
time_on: 10s
time_off: !lambda "return 1000;"
- autorepeat:
- delay: 1s
time_off: 100ms
time_on: 900ms
- delay: 5s
time_off: 100ms
time_on: 400ms
- lambda: |-
if (id(some_binary_sensor).state) {
return x;
} else {
return {};
}
- settle: 100ms
- timeout: 10s
on_state_change:
then:
- logger.log: