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_)
@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):
return cg.new_Pvariable(filter_id, config)
return cg.new_Pvariable(filter_id, *config)
@FILTER_REGISTRY.register("or", OrFilter, validate_filters)

View file

@ -315,19 +315,23 @@ optional<float> ThrottleFilter::new_value(float value) {
}
// 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) {
if (std::isnan(value)) {
if (std::isnan(this->last_value_)) {
return {};
} else {
if (this->percentage_mode_) {
this->current_delta_ = fabsf(value * this->delta_);
}
return this->last_value_ = value;
}
}
if (std::isnan(this->last_value_)) {
return this->last_value_ = value;
}
if (fabsf(value - this->last_value_) >= this->min_delta_) {
if (std::isnan(this->last_value_) || fabsf(value - this->last_value_) >= this->current_delta_) {
if (this->percentage_mode_) {
this->current_delta_ = fabsf(value * this->delta_);
}
return this->last_value_ = value;
}
return {};

View file

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

View file

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

View file

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