Update the delta filter to take a percentage value as well as an absolute value (#4391)

This commit is contained in:
Trent Houliston 2023-03-16 09:20:18 +11:00 committed by GitHub
parent 1b8b8cdd11
commit 25fb288016
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 29 additions and 10 deletions

View file

@ -466,9 +466,21 @@ async def lambda_filter_to_code(config, filter_id):
return cg.new_Pvariable(filter_id, lambda_) return cg.new_Pvariable(filter_id, lambda_)
@FILTER_REGISTRY.register("delta", DeltaFilter, cv.float_) def validate_delta(config):
try:
return (cv.positive_float(config), False)
except cv.Invalid:
pass
try:
return (cv.percentage(config), True)
except cv.Invalid:
pass
raise cv.Invalid("Delta filter requires a positive number or percentage value.")
@FILTER_REGISTRY.register("delta", DeltaFilter, validate_delta)
async def delta_filter_to_code(config, filter_id): async def delta_filter_to_code(config, filter_id):
return cg.new_Pvariable(filter_id, config) return cg.new_Pvariable(filter_id, *config)
@FILTER_REGISTRY.register("or", OrFilter, validate_filters) @FILTER_REGISTRY.register("or", OrFilter, validate_filters)

View file

@ -315,19 +315,23 @@ optional<float> ThrottleFilter::new_value(float value) {
} }
// DeltaFilter // DeltaFilter
DeltaFilter::DeltaFilter(float min_delta) : min_delta_(min_delta), last_value_(NAN) {} DeltaFilter::DeltaFilter(float delta, bool percentage_mode)
: delta_(delta), current_delta_(delta), percentage_mode_(percentage_mode), last_value_(NAN) {}
optional<float> DeltaFilter::new_value(float value) { optional<float> DeltaFilter::new_value(float value) {
if (std::isnan(value)) { if (std::isnan(value)) {
if (std::isnan(this->last_value_)) { if (std::isnan(this->last_value_)) {
return {}; return {};
} else { } else {
if (this->percentage_mode_) {
this->current_delta_ = fabsf(value * this->delta_);
}
return this->last_value_ = value; return this->last_value_ = value;
} }
} }
if (std::isnan(this->last_value_)) { if (std::isnan(this->last_value_) || fabsf(value - this->last_value_) >= this->current_delta_) {
return this->last_value_ = value; if (this->percentage_mode_) {
} this->current_delta_ = fabsf(value * this->delta_);
if (fabsf(value - this->last_value_) >= this->min_delta_) { }
return this->last_value_ = value; return this->last_value_ = value;
} }
return {}; return {};

View file

@ -325,12 +325,14 @@ class HeartbeatFilter : public Filter, public Component {
class DeltaFilter : public Filter { class DeltaFilter : public Filter {
public: public:
explicit DeltaFilter(float min_delta); explicit DeltaFilter(float delta, bool percentage_mode);
optional<float> new_value(float value) override; optional<float> new_value(float value) override;
protected: protected:
float min_delta_; float delta_;
float current_delta_;
bool percentage_mode_;
float last_value_{NAN}; float last_value_{NAN};
}; };

View file

@ -1097,7 +1097,7 @@ def possibly_negative_percentage(value):
if isinstance(value, str): if isinstance(value, str):
try: try:
if value.endswith("%"): if value.endswith("%"):
has_percent_sign = False has_percent_sign = True
value = float(value[:-1].rstrip()) / 100.0 value = float(value[:-1].rstrip()) / 100.0
else: else:
value = float(value) value = float(value)

View file

@ -392,6 +392,7 @@ sensor:
- heartbeat: 5s - heartbeat: 5s
- debounce: 0.1s - debounce: 0.1s
- delta: 5.0 - delta: 5.0
- delta: 1%
- or: - or:
- throttle: 1s - throttle: 1s
- delta: 5.0 - delta: 5.0