[binary_sensor] initial state refactor (#8648)

Co-authored-by: Zsombor Welker <flaktack@welker.hu>
This commit is contained in:
Clyde Stubbs 2025-05-01 13:58:35 +10:00 committed by GitHub
parent 8cd62c0308
commit 087ff865a7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 38 additions and 42 deletions

View File

@ -15,21 +15,17 @@ void BinarySensor::publish_state(bool state) {
if (!this->publish_dedup_.next(state)) if (!this->publish_dedup_.next(state))
return; return;
if (this->filter_list_ == nullptr) { if (this->filter_list_ == nullptr) {
this->send_state_internal(state, false); this->send_state_internal(state);
} else { } else {
this->filter_list_->input(state, false); this->filter_list_->input(state);
} }
} }
void BinarySensor::publish_initial_state(bool state) { void BinarySensor::publish_initial_state(bool state) {
if (!this->publish_dedup_.next(state)) this->has_state_ = false;
return; this->publish_state(state);
if (this->filter_list_ == nullptr) {
this->send_state_internal(state, true);
} else {
this->filter_list_->input(state, true);
} }
} void BinarySensor::send_state_internal(bool state) {
void BinarySensor::send_state_internal(bool state, bool is_initial) { bool is_initial = !this->has_state_;
if (is_initial) { if (is_initial) {
ESP_LOGD(TAG, "'%s': Sending initial state %s", this->get_name().c_str(), ONOFF(state)); ESP_LOGD(TAG, "'%s': Sending initial state %s", this->get_name().c_str(), ONOFF(state));
} else { } else {

View File

@ -67,7 +67,7 @@ class BinarySensor : public EntityBase, public EntityBase_DeviceClass {
// ========== INTERNAL METHODS ========== // ========== INTERNAL METHODS ==========
// (In most use cases you won't need these) // (In most use cases you won't need these)
void send_state_internal(bool state, bool is_initial); void send_state_internal(bool state);
/// Return whether this binary sensor has outputted a state. /// Return whether this binary sensor has outputted a state.
virtual bool has_state() const; virtual bool has_state() const;

View File

@ -9,37 +9,37 @@ namespace binary_sensor {
static const char *const TAG = "sensor.filter"; static const char *const TAG = "sensor.filter";
void Filter::output(bool value, bool is_initial) { void Filter::output(bool value) {
if (!this->dedup_.next(value)) if (!this->dedup_.next(value))
return; return;
if (this->next_ == nullptr) { if (this->next_ == nullptr) {
this->parent_->send_state_internal(value, is_initial); this->parent_->send_state_internal(value);
} else { } else {
this->next_->input(value, is_initial); this->next_->input(value);
} }
} }
void Filter::input(bool value, bool is_initial) { void Filter::input(bool value) {
auto b = this->new_value(value, is_initial); auto b = this->new_value(value);
if (b.has_value()) { if (b.has_value()) {
this->output(*b, is_initial); this->output(*b);
} }
} }
optional<bool> DelayedOnOffFilter::new_value(bool value, bool is_initial) { optional<bool> DelayedOnOffFilter::new_value(bool value) {
if (value) { if (value) {
this->set_timeout("ON_OFF", this->on_delay_.value(), [this, is_initial]() { this->output(true, is_initial); }); this->set_timeout("ON_OFF", this->on_delay_.value(), [this]() { this->output(true); });
} else { } else {
this->set_timeout("ON_OFF", this->off_delay_.value(), [this, is_initial]() { this->output(false, is_initial); }); this->set_timeout("ON_OFF", this->off_delay_.value(), [this]() { this->output(false); });
} }
return {}; return {};
} }
float DelayedOnOffFilter::get_setup_priority() const { return setup_priority::HARDWARE; } float DelayedOnOffFilter::get_setup_priority() const { return setup_priority::HARDWARE; }
optional<bool> DelayedOnFilter::new_value(bool value, bool is_initial) { optional<bool> DelayedOnFilter::new_value(bool value) {
if (value) { if (value) {
this->set_timeout("ON", this->delay_.value(), [this, is_initial]() { this->output(true, is_initial); }); this->set_timeout("ON", this->delay_.value(), [this]() { this->output(true); });
return {}; return {};
} else { } else {
this->cancel_timeout("ON"); this->cancel_timeout("ON");
@ -49,9 +49,9 @@ optional<bool> DelayedOnFilter::new_value(bool value, bool is_initial) {
float DelayedOnFilter::get_setup_priority() const { return setup_priority::HARDWARE; } float DelayedOnFilter::get_setup_priority() const { return setup_priority::HARDWARE; }
optional<bool> DelayedOffFilter::new_value(bool value, bool is_initial) { optional<bool> DelayedOffFilter::new_value(bool value) {
if (!value) { if (!value) {
this->set_timeout("OFF", this->delay_.value(), [this, is_initial]() { this->output(false, is_initial); }); this->set_timeout("OFF", this->delay_.value(), [this]() { this->output(false); });
return {}; return {};
} else { } else {
this->cancel_timeout("OFF"); this->cancel_timeout("OFF");
@ -61,11 +61,11 @@ optional<bool> DelayedOffFilter::new_value(bool value, bool is_initial) {
float DelayedOffFilter::get_setup_priority() const { return setup_priority::HARDWARE; } float DelayedOffFilter::get_setup_priority() const { return setup_priority::HARDWARE; }
optional<bool> InvertFilter::new_value(bool value, bool is_initial) { return !value; } optional<bool> InvertFilter::new_value(bool value) { return !value; }
AutorepeatFilter::AutorepeatFilter(std::vector<AutorepeatFilterTiming> timings) : timings_(std::move(timings)) {} AutorepeatFilter::AutorepeatFilter(std::vector<AutorepeatFilterTiming> timings) : timings_(std::move(timings)) {}
optional<bool> AutorepeatFilter::new_value(bool value, bool is_initial) { optional<bool> AutorepeatFilter::new_value(bool value) {
if (value) { if (value) {
// Ignore if already running // Ignore if already running
if (this->active_timing_ != 0) if (this->active_timing_ != 0)
@ -101,7 +101,7 @@ void AutorepeatFilter::next_timing_() {
void AutorepeatFilter::next_value_(bool val) { void AutorepeatFilter::next_value_(bool val) {
const AutorepeatFilterTiming &timing = this->timings_[this->active_timing_ - 2]; const AutorepeatFilterTiming &timing = this->timings_[this->active_timing_ - 2];
this->output(val, false); // This is at least the second one so not initial this->output(val);
this->set_timeout("ON_OFF", val ? timing.time_on : timing.time_off, [this, val]() { this->next_value_(!val); }); this->set_timeout("ON_OFF", val ? timing.time_on : timing.time_off, [this, val]() { this->next_value_(!val); });
} }
@ -109,18 +109,18 @@ float AutorepeatFilter::get_setup_priority() const { return setup_priority::HARD
LambdaFilter::LambdaFilter(std::function<optional<bool>(bool)> f) : f_(std::move(f)) {} LambdaFilter::LambdaFilter(std::function<optional<bool>(bool)> f) : f_(std::move(f)) {}
optional<bool> LambdaFilter::new_value(bool value, bool is_initial) { return this->f_(value); } optional<bool> LambdaFilter::new_value(bool value) { return this->f_(value); }
optional<bool> SettleFilter::new_value(bool value, bool is_initial) { optional<bool> SettleFilter::new_value(bool value) {
if (!this->steady_) { if (!this->steady_) {
this->set_timeout("SETTLE", this->delay_.value(), [this, value, is_initial]() { this->set_timeout("SETTLE", this->delay_.value(), [this, value]() {
this->steady_ = true; this->steady_ = true;
this->output(value, is_initial); this->output(value);
}); });
return {}; return {};
} else { } else {
this->steady_ = false; this->steady_ = false;
this->output(value, is_initial); this->output(value);
this->set_timeout("SETTLE", this->delay_.value(), [this]() { this->steady_ = true; }); this->set_timeout("SETTLE", this->delay_.value(), [this]() { this->steady_ = true; });
return value; return value;
} }

View File

@ -14,11 +14,11 @@ class BinarySensor;
class Filter { class Filter {
public: public:
virtual optional<bool> new_value(bool value, bool is_initial) = 0; virtual optional<bool> new_value(bool value) = 0;
void input(bool value, bool is_initial); void input(bool value);
void output(bool value, bool is_initial); void output(bool value);
protected: protected:
friend BinarySensor; friend BinarySensor;
@ -30,7 +30,7 @@ class Filter {
class DelayedOnOffFilter : public Filter, public Component { class DelayedOnOffFilter : public Filter, public Component {
public: public:
optional<bool> new_value(bool value, bool is_initial) override; optional<bool> new_value(bool value) override;
float get_setup_priority() const override; float get_setup_priority() const override;
@ -44,7 +44,7 @@ class DelayedOnOffFilter : public Filter, public Component {
class DelayedOnFilter : public Filter, public Component { class DelayedOnFilter : public Filter, public Component {
public: public:
optional<bool> new_value(bool value, bool is_initial) override; optional<bool> new_value(bool value) override;
float get_setup_priority() const override; float get_setup_priority() const override;
@ -56,7 +56,7 @@ class DelayedOnFilter : public Filter, public Component {
class DelayedOffFilter : public Filter, public Component { class DelayedOffFilter : public Filter, public Component {
public: public:
optional<bool> new_value(bool value, bool is_initial) override; optional<bool> new_value(bool value) override;
float get_setup_priority() const override; float get_setup_priority() const override;
@ -68,7 +68,7 @@ class DelayedOffFilter : public Filter, public Component {
class InvertFilter : public Filter { class InvertFilter : public Filter {
public: public:
optional<bool> new_value(bool value, bool is_initial) override; optional<bool> new_value(bool value) override;
}; };
struct AutorepeatFilterTiming { struct AutorepeatFilterTiming {
@ -86,7 +86,7 @@ class AutorepeatFilter : public Filter, public Component {
public: public:
explicit AutorepeatFilter(std::vector<AutorepeatFilterTiming> timings); explicit AutorepeatFilter(std::vector<AutorepeatFilterTiming> timings);
optional<bool> new_value(bool value, bool is_initial) override; optional<bool> new_value(bool value) override;
float get_setup_priority() const override; float get_setup_priority() const override;
@ -102,7 +102,7 @@ class LambdaFilter : public Filter {
public: public:
explicit LambdaFilter(std::function<optional<bool>(bool)> f); explicit LambdaFilter(std::function<optional<bool>(bool)> f);
optional<bool> new_value(bool value, bool is_initial) override; optional<bool> new_value(bool value) override;
protected: protected:
std::function<optional<bool>(bool)> f_; std::function<optional<bool>(bool)> f_;
@ -110,7 +110,7 @@ class LambdaFilter : public Filter {
class SettleFilter : public Filter, public Component { class SettleFilter : public Filter, public Component {
public: public:
optional<bool> new_value(bool value, bool is_initial) override; optional<bool> new_value(bool value) override;
float get_setup_priority() const override; float get_setup_priority() const override;