[dew_point] Add dew_point sensor component (#14441)

Co-authored-by: pre-commit-ci-lite[bot] <117423508+pre-commit-ci-lite[bot]@users.noreply.github.com>
Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com>
This commit is contained in:
CFlix
2026-03-10 22:17:13 +01:00
committed by GitHub
parent 6356e3def9
commit 9513edc468
9 changed files with 178 additions and 0 deletions
+1
View File
@@ -132,6 +132,7 @@ esphome/components/dashboard_import/* @esphome/core
esphome/components/datetime/* @jesserockz @rfdarter
esphome/components/debug/* @esphome/core
esphome/components/delonghi/* @grob6000
esphome/components/dew_point/* @CFlix
esphome/components/dfplayer/* @glmnet
esphome/components/dfrobot_sen0395/* @niklasweber
esphome/components/dht/* @OttoWinter
+1
View File
@@ -0,0 +1 @@
CODEOWNERS = ["@CFlix"]
@@ -0,0 +1,82 @@
#include "dew_point.h"
namespace esphome::dew_point {
static const char *const TAG = "dew_point.sensor";
void DewPointComponent::setup() {
// Register callbacks for sensor updates
if (this->temperature_sensor_ != nullptr) {
this->temperature_sensor_->add_on_state_callback([this](float state) {
this->temperature_value_ = state;
this->enable_loop();
});
// Get initial value
if (this->temperature_sensor_->has_state()) {
this->temperature_value_ = this->temperature_sensor_->get_state();
}
}
if (this->humidity_sensor_ != nullptr) {
this->humidity_sensor_->add_on_state_callback([this](float state) {
this->humidity_value_ = state;
this->enable_loop();
});
// Get initial value
if (this->humidity_sensor_->has_state()) {
this->humidity_value_ = this->humidity_sensor_->get_state();
}
}
}
void DewPointComponent::dump_config() {
LOG_SENSOR("", "Dew Point", this);
ESP_LOGCONFIG(TAG,
"Sources\n"
" Temperature: '%s'\n"
" Humidity: '%s'",
this->temperature_sensor_->get_name().c_str(), this->humidity_sensor_->get_name().c_str());
}
float DewPointComponent::get_setup_priority() const { return setup_priority::DATA; }
void DewPointComponent::loop() {
// Only run once
this->disable_loop();
// Check if we have valid values for both sensors
if (std::isnan(this->temperature_value_) || std::isnan(this->humidity_value_)) {
ESP_LOGW(TAG, "Temperature or humidity value is NaN, skipping calculation");
this->publish_state(NAN);
return;
}
// Check for valid humidity range
if (this->humidity_value_ <= 0.0f || this->humidity_value_ > 100.0f) {
ESP_LOGW(TAG, "Humidity value out of range (0-100): %.2f", this->humidity_value_);
this->publish_state(NAN);
return;
}
// Magnus formula constants
const float a{17.625f};
const float b{243.04f};
// Calculate dew point using Magnus formula
// Td = (b * alpha) / (a - alpha)
// where alpha = ln(RH/100) + (a * T) / (b + T)
const float alpha{std::log(this->humidity_value_ / 100.0f) +
(a * this->temperature_value_) / (b + this->temperature_value_)};
const float dew_point{(b * alpha) / (a - alpha)};
// Publish the calculated dew point
this->publish_state(dew_point);
ESP_LOGD(TAG, "'%s' >> %.1f°C (T: %.1f°C, RH: %.1f%%)", this->get_name().c_str(), dew_point, this->temperature_value_,
this->humidity_value_);
}
} // namespace esphome::dew_point
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#include "esphome/core/component.h"
#include "esphome/components/sensor/sensor.h"
namespace esphome::dew_point {
class DewPointComponent : public Component, public sensor::Sensor {
public:
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 setup() override;
void dump_config() override;
void loop() override;
float get_setup_priority() const override;
protected:
sensor::Sensor *temperature_sensor_{nullptr};
sensor::Sensor *humidity_sensor_{nullptr};
float temperature_value_{NAN};
float humidity_value_{NAN};
};
} // namespace esphome::dew_point
+46
View File
@@ -0,0 +1,46 @@
import esphome.codegen as cg
from esphome.components import sensor
import esphome.config_validation as cv
from esphome.const import (
CONF_HUMIDITY,
CONF_TEMPERATURE,
DEVICE_CLASS_TEMPERATURE,
STATE_CLASS_MEASUREMENT,
UNIT_CELSIUS,
)
DEPENDENCIES = ["sensor"]
dew_point_ns = cg.esphome_ns.namespace("dew_point")
DewPointComponent = dew_point_ns.class_(
"DewPointComponent", cg.Component, sensor.Sensor
)
CONFIG_SCHEMA = (
sensor.sensor_schema(
DewPointComponent,
unit_of_measurement=UNIT_CELSIUS,
accuracy_decimals=1,
device_class=DEVICE_CLASS_TEMPERATURE,
state_class=STATE_CLASS_MEASUREMENT,
icon="mdi:weather-rainy",
)
.extend(
{
cv.Required(CONF_TEMPERATURE): cv.use_id(sensor.Sensor),
cv.Required(CONF_HUMIDITY): cv.use_id(sensor.Sensor),
}
)
.extend(cv.COMPONENT_SCHEMA)
)
async def to_code(config):
var = await sensor.new_sensor(config)
await cg.register_component(var, config)
temperature_sensor = await cg.get_variable(config[CONF_TEMPERATURE])
cg.add(var.set_temperature_sensor(temperature_sensor))
humidity_sensor = await cg.get_variable(config[CONF_HUMIDITY])
cg.add(var.set_humidity_sensor(humidity_sensor))
+19
View File
@@ -0,0 +1,19 @@
sensor:
- platform: dew_point
name: Dew Point
temperature: template_temperature
humidity: template_humidity
- platform: template
id: template_humidity
lambda: |-
if (millis() > 10000) {
return 0.6;
}
return 0.0;
- platform: template
id: template_temperature
lambda: |-
if (millis() > 10000) {
return 42.0;
}
return 0.0;
@@ -0,0 +1 @@
<<: !include common.yaml
@@ -0,0 +1 @@
<<: !include common.yaml
@@ -0,0 +1 @@
<<: !include common.yaml