[sensor] Make some values templatable (#7735)

This commit is contained in:
Clyde Stubbs 2024-11-11 12:18:05 +11:00 committed by GitHub
parent c35240ca32
commit d885d65c9b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 65 additions and 36 deletions

View file

@ -335,19 +335,28 @@ def sensor_schema(
return SENSOR_SCHEMA.extend(schema) return SENSOR_SCHEMA.extend(schema)
@FILTER_REGISTRY.register("offset", OffsetFilter, cv.float_) @FILTER_REGISTRY.register("offset", OffsetFilter, cv.templatable(cv.float_))
async def offset_filter_to_code(config, filter_id): async def offset_filter_to_code(config, filter_id):
return cg.new_Pvariable(filter_id, config) template_ = await cg.templatable(config, [], float)
return cg.new_Pvariable(filter_id, template_)
@FILTER_REGISTRY.register("multiply", MultiplyFilter, cv.float_) @FILTER_REGISTRY.register("multiply", MultiplyFilter, cv.templatable(cv.float_))
async def multiply_filter_to_code(config, filter_id): async def multiply_filter_to_code(config, filter_id):
return cg.new_Pvariable(filter_id, config) template_ = await cg.templatable(config, [], float)
return cg.new_Pvariable(filter_id, template_)
@FILTER_REGISTRY.register("filter_out", FilterOutValueFilter, cv.float_) @FILTER_REGISTRY.register(
"filter_out",
FilterOutValueFilter,
cv.Any(cv.templatable(cv.float_), [cv.templatable(cv.float_)]),
)
async def filter_out_filter_to_code(config, filter_id): async def filter_out_filter_to_code(config, filter_id):
return cg.new_Pvariable(filter_id, config) if not isinstance(config, list):
config = [config]
template_ = [await cg.templatable(x, [], float) for x in config]
return cg.new_Pvariable(filter_id, template_)
QUANTILE_SCHEMA = cv.All( QUANTILE_SCHEMA = cv.All(
@ -573,7 +582,7 @@ async def heartbeat_filter_to_code(config, filter_id):
TIMEOUT_SCHEMA = cv.maybe_simple_value( TIMEOUT_SCHEMA = cv.maybe_simple_value(
{ {
cv.Required(CONF_TIMEOUT): cv.positive_time_period_milliseconds, cv.Required(CONF_TIMEOUT): cv.positive_time_period_milliseconds,
cv.Optional(CONF_VALUE, default="nan"): cv.float_, cv.Optional(CONF_VALUE, default="nan"): cv.templatable(cv.float_),
}, },
key=CONF_TIMEOUT, key=CONF_TIMEOUT,
) )
@ -581,7 +590,8 @@ TIMEOUT_SCHEMA = cv.maybe_simple_value(
@FILTER_REGISTRY.register("timeout", TimeoutFilter, TIMEOUT_SCHEMA) @FILTER_REGISTRY.register("timeout", TimeoutFilter, TIMEOUT_SCHEMA)
async def timeout_filter_to_code(config, filter_id): async def timeout_filter_to_code(config, filter_id):
var = cg.new_Pvariable(filter_id, config[CONF_TIMEOUT], config[CONF_VALUE]) template_ = await cg.templatable(config[CONF_VALUE], [], float)
var = cg.new_Pvariable(filter_id, config[CONF_TIMEOUT], template_)
await cg.register_component(var, {}) await cg.register_component(var, {})
return var return var

View file

@ -288,36 +288,36 @@ optional<float> LambdaFilter::new_value(float value) {
} }
// OffsetFilter // OffsetFilter
OffsetFilter::OffsetFilter(float offset) : offset_(offset) {} OffsetFilter::OffsetFilter(TemplatableValue<float> offset) : offset_(std::move(offset)) {}
optional<float> OffsetFilter::new_value(float value) { return value + this->offset_; } optional<float> OffsetFilter::new_value(float value) { return value + this->offset_.value(); }
// MultiplyFilter // MultiplyFilter
MultiplyFilter::MultiplyFilter(float multiplier) : multiplier_(multiplier) {} MultiplyFilter::MultiplyFilter(TemplatableValue<float> multiplier) : multiplier_(std::move(multiplier)) {}
optional<float> MultiplyFilter::new_value(float value) { return value * this->multiplier_; } optional<float> MultiplyFilter::new_value(float value) { return value * this->multiplier_.value(); }
// FilterOutValueFilter // FilterOutValueFilter
FilterOutValueFilter::FilterOutValueFilter(float value_to_filter_out) : value_to_filter_out_(value_to_filter_out) {} FilterOutValueFilter::FilterOutValueFilter(std::vector<TemplatableValue<float>> values_to_filter_out)
: values_to_filter_out_(std::move(values_to_filter_out)) {}
optional<float> FilterOutValueFilter::new_value(float value) { optional<float> FilterOutValueFilter::new_value(float value) {
if (std::isnan(this->value_to_filter_out_)) { int8_t accuracy = this->parent_->get_accuracy_decimals();
if (std::isnan(value)) { float accuracy_mult = powf(10.0f, accuracy);
return {}; for (auto filter_value : this->values_to_filter_out_) {
} else { if (std::isnan(filter_value.value())) {
return value; if (std::isnan(value)) {
return {};
}
continue;
} }
} else { float rounded_filter_out = roundf(accuracy_mult * filter_value.value());
int8_t accuracy = this->parent_->get_accuracy_decimals();
float accuracy_mult = powf(10.0f, accuracy);
float rounded_filter_out = roundf(accuracy_mult * this->value_to_filter_out_);
float rounded_value = roundf(accuracy_mult * value); float rounded_value = roundf(accuracy_mult * value);
if (rounded_filter_out == rounded_value) { if (rounded_filter_out == rounded_value) {
return {}; return {};
} else {
return value;
} }
} }
return value;
} }
// ThrottleFilter // ThrottleFilter
@ -383,11 +383,12 @@ void OrFilter::initialize(Sensor *parent, Filter *next) {
// TimeoutFilter // TimeoutFilter
optional<float> TimeoutFilter::new_value(float value) { optional<float> TimeoutFilter::new_value(float value) {
this->set_timeout("timeout", this->time_period_, [this]() { this->output(this->value_); }); this->set_timeout("timeout", this->time_period_, [this]() { this->output(this->value_.value()); });
return value; return value;
} }
TimeoutFilter::TimeoutFilter(uint32_t time_period, float new_value) : time_period_(time_period), value_(new_value) {} TimeoutFilter::TimeoutFilter(uint32_t time_period, TemplatableValue<float> new_value)
: time_period_(time_period), value_(std::move(new_value)) {}
float TimeoutFilter::get_setup_priority() const { return setup_priority::HARDWARE; } float TimeoutFilter::get_setup_priority() const { return setup_priority::HARDWARE; }
// DebounceFilter // DebounceFilter

View file

@ -5,6 +5,7 @@
#include <vector> #include <vector>
#include "esphome/core/component.h" #include "esphome/core/component.h"
#include "esphome/core/helpers.h" #include "esphome/core/helpers.h"
#include "esphome/core/automation.h"
namespace esphome { namespace esphome {
namespace sensor { namespace sensor {
@ -273,34 +274,33 @@ class LambdaFilter : public Filter {
/// A simple filter that adds `offset` to each value it receives. /// A simple filter that adds `offset` to each value it receives.
class OffsetFilter : public Filter { class OffsetFilter : public Filter {
public: public:
explicit OffsetFilter(float offset); explicit OffsetFilter(TemplatableValue<float> offset);
optional<float> new_value(float value) override; optional<float> new_value(float value) override;
protected: protected:
float offset_; TemplatableValue<float> offset_;
}; };
/// A simple filter that multiplies to each value it receives by `multiplier`. /// A simple filter that multiplies to each value it receives by `multiplier`.
class MultiplyFilter : public Filter { class MultiplyFilter : public Filter {
public: public:
explicit MultiplyFilter(float multiplier); explicit MultiplyFilter(TemplatableValue<float> multiplier);
optional<float> new_value(float value) override; optional<float> new_value(float value) override;
protected: protected:
float multiplier_; TemplatableValue<float> multiplier_;
}; };
/// A simple filter that only forwards the filter chain if it doesn't receive `value_to_filter_out`. /// A simple filter that only forwards the filter chain if it doesn't receive `value_to_filter_out`.
class FilterOutValueFilter : public Filter { class FilterOutValueFilter : public Filter {
public: public:
explicit FilterOutValueFilter(float value_to_filter_out); explicit FilterOutValueFilter(std::vector<TemplatableValue<float>> values_to_filter_out);
optional<float> new_value(float value) override; optional<float> new_value(float value) override;
protected: protected:
float value_to_filter_out_; std::vector<TemplatableValue<float>> values_to_filter_out_;
}; };
class ThrottleFilter : public Filter { class ThrottleFilter : public Filter {
@ -316,8 +316,7 @@ class ThrottleFilter : public Filter {
class TimeoutFilter : public Filter, public Component { class TimeoutFilter : public Filter, public Component {
public: public:
explicit TimeoutFilter(uint32_t time_period, float new_value); explicit TimeoutFilter(uint32_t time_period, TemplatableValue<float> new_value);
void set_value(float new_value) { this->value_ = new_value; }
optional<float> new_value(float value) override; optional<float> new_value(float value) override;
@ -325,7 +324,7 @@ class TimeoutFilter : public Filter, public Component {
protected: protected:
uint32_t time_period_; uint32_t time_period_;
float value_; TemplatableValue<float> value_;
}; };
class DebounceFilter : public Filter, public Component { class DebounceFilter : public Filter, public Component {

View file

@ -9,6 +9,25 @@ sensor:
return 0.0; return 0.0;
} }
update_interval: 60s update_interval: 60s
filters:
- offset: 10
- multiply: 1
- offset: !lambda return 10;
- multiply: !lambda return 2;
- filter_out:
- 10
- 20
- !lambda return 10;
- filter_out: 10
- filter_out: !lambda return NAN;
- timeout:
timeout: 10s
value: !lambda return 10;
- timeout:
timeout: 1h
value: 20.0
- timeout:
timeout: 1d
esphome: esphome:
on_boot: on_boot: