11 namespace combination {
13 static const char *
const TAG =
"combination";
16 LOG_SENSOR(
"",
"Combination Sensor:",
this);
17 ESP_LOGCONFIG(TAG,
" Combination Type: %s", LOG_STR_ARG(combo_type));
24 this->sensor_pairs_.emplace_back(sensor, stddev);
28 this->add_source(sensor, std::function<
float(
float)>{[stddev](
float x) ->
float {
return stddev; }});
32 ESP_LOGCONFIG(TAG,
" Source Sensors:");
33 for (
const auto &sensor : this->sensors_) {
34 ESP_LOGCONFIG(TAG,
" - %s", sensor->get_name().c_str());
39 ESP_LOGCONFIG(TAG,
" Source Sensors:");
40 for (
const auto &sensor : this->sensor_pairs_) {
41 auto &entity = *sensor.first;
42 ESP_LOGCONFIG(TAG,
" - %s", entity.get_name().c_str());
47 for (
const auto &sensor : this->sensors_) {
50 sensor->add_on_state_callback(
51 [
this](
float value) ->
void { this->
defer(
"update", [
this, value]() { this->handle_new_value(value); }); });
57 ESP_LOGCONFIG(TAG,
" Update variance: %f per ms", this->update_variance_value_);
59 if (this->std_dev_sensor_ !=
nullptr) {
60 LOG_SENSOR(
" ",
"Standard Deviation Sensor:", this->std_dev_sensor_);
65 for (
const auto &sensor : this->sensor_pairs_) {
66 const auto stddev = sensor.second;
67 sensor.first->add_on_state_callback([
this, stddev](
float x) ->
void { this->correct_(x, stddev(x)); });
75 auto dt = now - this->last_update_;
76 auto dv = this->update_variance_value_ * dt;
77 this->variance_ += dv;
78 this->last_update_ = now;
82 if (std::isnan(value) || std::isinf(stddev)) {
86 if (std::isnan(this->state_) || std::isinf(this->variance_)) {
88 this->variance_ = stddev * stddev;
89 if (this->std_dev_sensor_ !=
nullptr) {
90 this->std_dev_sensor_->publish_state(stddev);
95 this->update_variance_();
99 const bool this_first = this->variance_ < (stddev * stddev);
100 const float mu1 = this_first ? this->state_ : value;
101 const float mu2 = this_first ? value : this->state_;
103 const float var1 = this_first ? this->variance_ : stddev * stddev;
104 const float var2 = this_first ? stddev * stddev : this->variance_;
106 const float mu = mu1 + var1 * (mu2 - mu1) / (var1 + var2);
107 const float var = var1 - (var1 * var1) / (var1 + var2);
111 this->variance_ = var;
114 if (this->std_dev_sensor_ !=
nullptr) {
115 this->std_dev_sensor_->publish_state(std::sqrt(var));
120 for (
const auto &sensor : this->sensor_pairs_) {
123 sensor.first->add_on_state_callback(
124 [
this](
float value) ->
void { this->
defer(
"update", [
this, value]() { this->handle_new_value(value); }); });
131 if (!std::isfinite(value))
136 for (
const auto &sensor : this->sensor_pairs_) {
137 const float sensor_state = sensor.first->state;
138 if (std::isfinite(sensor_state)) {
139 sum += sensor_state * sensor.second(sensor_state);
147 if (!std::isfinite(value))
150 float max_value = (-1) * std::numeric_limits<float>::infinity();
152 for (
const auto &sensor : this->sensors_) {
153 if (std::isfinite(sensor->state)) {
154 max_value = std::max(max_value, sensor->state);
162 if (!std::isfinite(value))
168 for (
const auto &sensor : this->sensors_) {
169 if (std::isfinite(sensor->state)) {
171 sum += sensor->state;
175 float mean = sum / count;
183 if (!std::isfinite(value))
186 std::vector<float> sensor_states;
187 for (
const auto &sensor : this->sensors_) {
188 if (std::isfinite(sensor->state)) {
189 sensor_states.push_back(sensor->state);
193 sort(sensor_states.begin(), sensor_states.end());
194 size_t sensor_states_size = sensor_states.size();
198 if (sensor_states_size) {
199 if (sensor_states_size % 2) {
201 median = sensor_states[sensor_states_size / 2];
204 median = (sensor_states[sensor_states_size / 2] + sensor_states[sensor_states_size / 2 - 1]) / 2.0;
212 if (!std::isfinite(value))
215 float min_value = std::numeric_limits<float>::infinity();
217 for (
const auto &sensor : this->sensors_) {
218 if (std::isfinite(sensor->state)) {
219 min_value = std::min(min_value, sensor->state);
231 if (!std::isfinite(value))
234 std::vector<float> sensor_states;
235 for (
const auto &sensor : this->sensors_) {
236 if (std::isfinite(sensor->state)) {
237 sensor_states.push_back(sensor->state);
241 sort(sensor_states.begin(), sensor_states.end());
243 float range = sensor_states.back() - sensor_states.front();
248 if (!std::isfinite(value))
252 for (
const auto &sensor : this->sensors_) {
253 if (std::isfinite(sensor->state)) {
254 sum += sensor->state;
void correct_(float value, float stddev)
void add_source(Sensor *sensor)
void handle_new_value(float value) override
void log_config_(const LogString *combo_type)
Logs the sensor for use in dump_config.
void defer(const std::string &name, std::function< void()> &&f)
Defer a callback to the next loop() call.
void handle_new_value(float value) override
uint32_t IRAM_ATTR HOT millis()
void add_source(Sensor *sensor, std::function< float(float)> const &stddev)
void setup() override
Adds a callback to each source sensor.
void log_source_sensors() override
Logs all source sensor's names in sensors_.
void handle_new_value(float value) override
void publish_state(float state)
Publish a new state to the front-end.
void handle_new_value(float value) override
void handle_new_value(float value)
void log_source_sensors() override
Logs all source sensor's names in sensor_pairs_.
Implementation of SPI Controller mode.
void handle_new_value(float value) override
esphome::sensor::Sensor * sensor
void dump_config() override
void handle_new_value(float value) override
virtual void log_source_sensors()=0
Logs all source sensor's names.