mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	[sensor] Make some values templatable (#7735)
This commit is contained in:
		| @@ -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 | ||||||
|  |  | ||||||
|   | |||||||
| @@ -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 | ||||||
|   | |||||||
| @@ -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 { | ||||||
|   | |||||||
| @@ -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: | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user