From cb23f9453f29c8f83ac6bf9e4b0ddd3f2b33d91c Mon Sep 17 00:00:00 2001 From: CFlix <38142312+CFlix@users.noreply.github.com> Date: Thu, 19 Mar 2026 14:09:00 +0100 Subject: [PATCH] [absolute_humidity] loop() improvement (#14684) Co-authored-by: DAVe3283 --- .../absolute_humidity/absolute_humidity.cpp | 102 +++++++++--------- .../absolute_humidity/absolute_humidity.h | 20 +--- 2 files changed, 55 insertions(+), 67 deletions(-) diff --git a/esphome/components/absolute_humidity/absolute_humidity.cpp b/esphome/components/absolute_humidity/absolute_humidity.cpp index 40676f8655..3137a59fad 100644 --- a/esphome/components/absolute_humidity/absolute_humidity.cpp +++ b/esphome/components/absolute_humidity/absolute_humidity.cpp @@ -1,22 +1,29 @@ #include "esphome/core/log.h" #include "absolute_humidity.h" -namespace esphome { -namespace absolute_humidity { +namespace esphome::absolute_humidity { -static const char *const TAG = "absolute_humidity.sensor"; +static const char *const TAG{"absolute_humidity.sensor"}; void AbsoluteHumidityComponent::setup() { + this->temperature_sensor_->add_on_state_callback([this](float state) { + this->temperature_ = state; + this->enable_loop(); + }); ESP_LOGD(TAG, " Added callback for temperature '%s'", this->temperature_sensor_->get_name().c_str()); - this->temperature_sensor_->add_on_state_callback([this](float state) { this->temperature_callback_(state); }); + // Get initial value if (this->temperature_sensor_->has_state()) { - this->temperature_callback_(this->temperature_sensor_->get_state()); + this->temperature_ = this->temperature_sensor_->get_state(); } + this->humidity_sensor_->add_on_state_callback([this](float state) { + this->humidity_ = state; + this->enable_loop(); + }); ESP_LOGD(TAG, " Added callback for relative humidity '%s'", this->humidity_sensor_->get_name().c_str()); - this->humidity_sensor_->add_on_state_callback([this](float state) { this->humidity_callback_(state); }); + // Get initial value if (this->humidity_sensor_->has_state()) { - this->humidity_callback_(this->humidity_sensor_->get_state()); + this->humidity_ = this->humidity_sensor_->get_state(); } } @@ -46,14 +53,12 @@ void AbsoluteHumidityComponent::dump_config() { } void AbsoluteHumidityComponent::loop() { - if (!this->next_update_) { - return; - } - this->next_update_ = false; + // Only run once + this->disable_loop(); // Ensure we have source data - const bool no_temperature = std::isnan(this->temperature_); - const bool no_humidity = std::isnan(this->humidity_); + const bool no_temperature{std::isnan(this->temperature_)}; + const bool no_humidity{std::isnan(this->humidity_)}; if (no_temperature || no_humidity) { if (no_temperature) { ESP_LOGW(TAG, "No valid state from temperature sensor!"); @@ -67,9 +72,9 @@ void AbsoluteHumidityComponent::loop() { } // Convert to desired units - const float temperature_c = this->temperature_; - const float temperature_k = temperature_c + 273.15; - const float hr = this->humidity_ / 100; + const float temperature_c{this->temperature_}; + const float temperature_k{temperature_c + 273.15f}; + const float hr{this->humidity_ / 100.0f}; // Calculate saturation vapor pressure float es; @@ -90,7 +95,7 @@ void AbsoluteHumidityComponent::loop() { } // Calculate absolute humidity - const float absolute_humidity = vapor_density(es, hr, temperature_k); + const float absolute_humidity{vapor_density(es, hr, temperature_k)}; ESP_LOGD(TAG, "Saturation vapor pressure %f kPa, absolute humidity %f g/m³", es, absolute_humidity); @@ -103,16 +108,16 @@ void AbsoluteHumidityComponent::loop() { // More accurate than Tetens in normal meteorologic conditions float AbsoluteHumidityComponent::es_buck(float temperature_c) { float a, b, c, d; - if (temperature_c >= 0) { - a = 0.61121; - b = 18.678; - c = 234.5; - d = 257.14; + if (temperature_c >= 0.0f) { + a = 0.61121f; + b = 18.678f; + c = 234.5f; + d = 257.14f; } else { - a = 0.61115; - b = 18.678; - c = 233.7; - d = 279.82; + a = 0.61115f; + b = 18.678f; + c = 233.7f; + d = 279.82f; } return a * expf((b - (temperature_c / c)) * (temperature_c / (d + temperature_c))); } @@ -120,14 +125,14 @@ float AbsoluteHumidityComponent::es_buck(float temperature_c) { // Tetens equation (https://en.wikipedia.org/wiki/Tetens_equation) float AbsoluteHumidityComponent::es_tetens(float temperature_c) { float a, b; - if (temperature_c >= 0) { - a = 17.27; - b = 237.3; + if (temperature_c >= 0.0f) { + a = 17.27f; + b = 237.3f; } else { - a = 21.875; - b = 265.5; + a = 21.875f; + b = 265.5f; } - return 0.61078 * expf((a * temperature_c) / (temperature_c + b)); + return 0.61078f * expf((a * temperature_c) / (temperature_c + b)); } // Wobus equation @@ -146,18 +151,18 @@ float AbsoluteHumidityComponent::es_wobus(float t) { // // Baker, Schlatter 17-MAY-1982 Original version. - const float c0 = +0.99999683e00; - const float c1 = -0.90826951e-02; - const float c2 = +0.78736169e-04; - const float c3 = -0.61117958e-06; - const float c4 = +0.43884187e-08; - const float c5 = -0.29883885e-10; - const float c6 = +0.21874425e-12; - const float c7 = -0.17892321e-14; - const float c8 = +0.11112018e-16; - const float c9 = -0.30994571e-19; - const float p = c0 + t * (c1 + t * (c2 + t * (c3 + t * (c4 + t * (c5 + t * (c6 + t * (c7 + t * (c8 + t * (c9))))))))); - return 0.61078 / pow(p, 8); + constexpr float c0{+0.99999683e+00f}; + constexpr float c1{-0.90826951e-02f}; + constexpr float c2{+0.78736169e-04f}; + constexpr float c3{-0.61117958e-06f}; + constexpr float c4{+0.43884187e-08f}; + constexpr float c5{-0.29883885e-10f}; + constexpr float c6{+0.21874425e-12f}; + constexpr float c7{-0.17892321e-14f}; + constexpr float c8{+0.11112018e-16f}; + constexpr float c9{-0.30994571e-19f}; + const float p{c0 + t * (c1 + t * (c2 + t * (c3 + t * (c4 + t * (c5 + t * (c6 + t * (c7 + t * (c8 + t * (c9)))))))))}; + return 0.61078f / powf(p, 8.0f); } // From https://www.environmentalbiophysics.org/chalk-talk-how-to-calculate-absolute-humidity/ @@ -168,11 +173,10 @@ float AbsoluteHumidityComponent::vapor_density(float es, float hr, float ta) { // hr = relative humidity [0-1] // ta = absolute temperature (K) - const float ea = hr * es * 1000; // vapor pressure of the air (Pa) - const float mw = 18.01528; // molar mass of water (g⋅mol⁻¹) - const float r = 8.31446261815324; // molar gas constant (J⋅K⁻¹) + const float ea{hr * es * 1000.0f}; // vapor pressure of the air (Pa) + const float mw{18.01528f}; // molar mass of water (g⋅mol⁻¹) + const float r{8.31446261815324f}; // molar gas constant (J⋅K⁻¹) return (ea * mw) / (r * ta); } -} // namespace absolute_humidity -} // namespace esphome +} // namespace esphome::absolute_humidity diff --git a/esphome/components/absolute_humidity/absolute_humidity.h b/esphome/components/absolute_humidity/absolute_humidity.h index 71feee2c42..be28d3dc50 100644 --- a/esphome/components/absolute_humidity/absolute_humidity.h +++ b/esphome/components/absolute_humidity/absolute_humidity.h @@ -3,8 +3,7 @@ #include "esphome/core/component.h" #include "esphome/components/sensor/sensor.h" -namespace esphome { -namespace absolute_humidity { +namespace esphome::absolute_humidity { /// Enum listing all implemented saturation vapor pressure equations. enum SaturationVaporPressureEquation { @@ -16,8 +15,6 @@ enum SaturationVaporPressureEquation { /// This class implements calculation of absolute humidity from temperature and relative humidity. class AbsoluteHumidityComponent : public sensor::Sensor, public Component { public: - AbsoluteHumidityComponent() = default; - void set_temperature_sensor(sensor::Sensor *temperature_sensor) { this->temperature_sensor_ = temperature_sensor; } void set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; } void set_equation(SaturationVaporPressureEquation equation) { this->equation_ = equation; } @@ -27,15 +24,6 @@ class AbsoluteHumidityComponent : public sensor::Sensor, public Component { void loop() override; protected: - void temperature_callback_(float state) { - this->next_update_ = true; - this->temperature_ = state; - } - void humidity_callback_(float state) { - this->next_update_ = true; - this->humidity_ = state; - } - /** Buck equation for saturation vapor pressure in kPa. * * @param temperature_c Air temperature in °C. @@ -57,19 +45,15 @@ class AbsoluteHumidityComponent : public sensor::Sensor, public Component { * @param es Saturation vapor pressure in kPa. * @param hr Relative humidity 0 to 1. * @param ta Absolute temperature in K. - * @param heater_duration The duration in ms that the heater should turn on for when measuring. */ static float vapor_density(float es, float hr, float ta); sensor::Sensor *temperature_sensor_{nullptr}; sensor::Sensor *humidity_sensor_{nullptr}; - bool next_update_{false}; - float temperature_{NAN}; float humidity_{NAN}; SaturationVaporPressureEquation equation_; }; -} // namespace absolute_humidity -} // namespace esphome +} // namespace esphome::absolute_humidity