From 25f03074ab271f0f861548df4e2e634c67247410 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sun, 19 Oct 2025 03:10:07 -0500 Subject: [PATCH 1/3] [web_server] Update to use new climate API (#11363) --- esphome/components/web_server/web_server.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index f18f21b16b..1d08ef5a35 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -1325,7 +1325,7 @@ std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_conf root["max_temp"] = value_accuracy_to_string(traits.get_visual_max_temperature(), target_accuracy); root["min_temp"] = value_accuracy_to_string(traits.get_visual_min_temperature(), target_accuracy); root["step"] = traits.get_visual_target_temperature_step(); - if (traits.get_supports_action()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_ACTION)) { root["action"] = PSTR_LOCAL(climate_action_to_string(obj->action)); root["state"] = root["action"]; has_state = true; @@ -1345,14 +1345,15 @@ std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_conf if (traits.get_supports_swing_modes()) { root["swing_mode"] = PSTR_LOCAL(climate_swing_mode_to_string(obj->swing_mode)); } - if (traits.get_supports_current_temperature()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE)) { if (!std::isnan(obj->current_temperature)) { root["current_temperature"] = value_accuracy_to_string(obj->current_temperature, current_accuracy); } else { root["current_temperature"] = "NA"; } } - if (traits.get_supports_two_point_target_temperature()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE | + climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE)) { root["target_temperature_low"] = value_accuracy_to_string(obj->target_temperature_low, target_accuracy); root["target_temperature_high"] = value_accuracy_to_string(obj->target_temperature_high, target_accuracy); if (!has_state) { From b4d9fddd074481909824d3fe21b62323d912f5ca Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sun, 19 Oct 2025 03:11:10 -0500 Subject: [PATCH 2/3] [mqtt] Update to use new climate API (#11360) --- esphome/components/mqtt/mqtt_climate.cpp | 30 ++++++++++++++---------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/esphome/components/mqtt/mqtt_climate.cpp b/esphome/components/mqtt/mqtt_climate.cpp index e16f097812..a6f4e0a201 100644 --- a/esphome/components/mqtt/mqtt_climate.cpp +++ b/esphome/components/mqtt/mqtt_climate.cpp @@ -17,11 +17,11 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo // NOLINTBEGIN(clang-analyzer-cplusplus.NewDeleteLeaks) false positive with ArduinoJson auto traits = this->device_->get_traits(); // current_temperature_topic - if (traits.get_supports_current_temperature()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE)) { root[MQTT_CURRENT_TEMPERATURE_TOPIC] = this->get_current_temperature_state_topic(); } // current_humidity_topic - if (traits.get_supports_current_humidity()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_HUMIDITY)) { root[MQTT_CURRENT_HUMIDITY_TOPIC] = this->get_current_humidity_state_topic(); } // mode_command_topic @@ -45,7 +45,8 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo if (traits.supports_mode(CLIMATE_MODE_HEAT_COOL)) modes.add("heat_cool"); - if (traits.get_supports_two_point_target_temperature()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE | + climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE)) { // temperature_low_command_topic root[MQTT_TEMPERATURE_LOW_COMMAND_TOPIC] = this->get_target_temperature_low_command_topic(); // temperature_low_state_topic @@ -61,7 +62,7 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo root[MQTT_TEMPERATURE_STATE_TOPIC] = this->get_target_temperature_state_topic(); } - if (traits.get_supports_target_humidity()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TARGET_HUMIDITY)) { // target_humidity_command_topic root[MQTT_TARGET_HUMIDITY_COMMAND_TOPIC] = this->get_target_humidity_command_topic(); // target_humidity_state_topic @@ -109,7 +110,7 @@ void MQTTClimateComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryCo presets.add(preset); } - if (traits.get_supports_action()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_ACTION)) { // action_topic root[MQTT_ACTION_TOPIC] = this->get_action_state_topic(); } @@ -174,7 +175,8 @@ void MQTTClimateComponent::setup() { call.perform(); }); - if (traits.get_supports_two_point_target_temperature()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE | + climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE)) { this->subscribe(this->get_target_temperature_low_command_topic(), [this](const std::string &topic, const std::string &payload) { auto val = parse_number(payload); @@ -211,7 +213,7 @@ void MQTTClimateComponent::setup() { }); } - if (traits.get_supports_target_humidity()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TARGET_HUMIDITY)) { this->subscribe(this->get_target_humidity_command_topic(), [this](const std::string &topic, const std::string &payload) { auto val = parse_number(payload); @@ -290,12 +292,14 @@ bool MQTTClimateComponent::publish_state_() { success = false; int8_t target_accuracy = traits.get_target_temperature_accuracy_decimals(); int8_t current_accuracy = traits.get_current_temperature_accuracy_decimals(); - if (traits.get_supports_current_temperature() && !std::isnan(this->device_->current_temperature)) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE) && + !std::isnan(this->device_->current_temperature)) { std::string payload = value_accuracy_to_string(this->device_->current_temperature, current_accuracy); if (!this->publish(this->get_current_temperature_state_topic(), payload)) success = false; } - if (traits.get_supports_two_point_target_temperature()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE | + climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE)) { std::string payload = value_accuracy_to_string(this->device_->target_temperature_low, target_accuracy); if (!this->publish(this->get_target_temperature_low_state_topic(), payload)) success = false; @@ -308,12 +312,14 @@ bool MQTTClimateComponent::publish_state_() { success = false; } - if (traits.get_supports_current_humidity() && !std::isnan(this->device_->current_humidity)) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_HUMIDITY) && + !std::isnan(this->device_->current_humidity)) { std::string payload = value_accuracy_to_string(this->device_->current_humidity, 0); if (!this->publish(this->get_current_humidity_state_topic(), payload)) success = false; } - if (traits.get_supports_target_humidity() && !std::isnan(this->device_->target_humidity)) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TARGET_HUMIDITY) && + !std::isnan(this->device_->target_humidity)) { std::string payload = value_accuracy_to_string(this->device_->target_humidity, 0); if (!this->publish(this->get_target_humidity_state_topic(), payload)) success = false; @@ -357,7 +363,7 @@ bool MQTTClimateComponent::publish_state_() { success = false; } - if (traits.get_supports_action()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_ACTION)) { const char *payload; switch (this->device_->action) { case CLIMATE_ACTION_OFF: From ddf1b67e49bc8859d3fa472582582960a1fbd06c Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Sun, 19 Oct 2025 03:11:44 -0500 Subject: [PATCH 3/3] [prometheus] Update to use new climate API (#11361) --- esphome/components/prometheus/prometheus_handler.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/esphome/components/prometheus/prometheus_handler.cpp b/esphome/components/prometheus/prometheus_handler.cpp index 68ef18e5ce..6e7ed6f79f 100644 --- a/esphome/components/prometheus/prometheus_handler.cpp +++ b/esphome/components/prometheus/prometheus_handler.cpp @@ -916,7 +916,7 @@ void PrometheusHandler::climate_row_(AsyncResponseStream *stream, climate::Clima auto min_temp_value = value_accuracy_to_string(traits.get_visual_min_temperature(), target_accuracy); climate_value_row_(stream, obj, area, node, friendly_name, min_temp, min_temp_value); // now check optional traits - if (traits.get_supports_current_temperature()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_TEMPERATURE)) { std::string current_temp = "current_temperature"; if (std::isnan(obj->current_temperature)) { climate_failed_row_(stream, obj, area, node, friendly_name, current_temp, true); @@ -927,7 +927,7 @@ void PrometheusHandler::climate_row_(AsyncResponseStream *stream, climate::Clima climate_failed_row_(stream, obj, area, node, friendly_name, current_temp, false); } } - if (traits.get_supports_current_humidity()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_HUMIDITY)) { std::string current_humidity = "current_humidity"; if (std::isnan(obj->current_humidity)) { climate_failed_row_(stream, obj, area, node, friendly_name, current_humidity, true); @@ -938,7 +938,7 @@ void PrometheusHandler::climate_row_(AsyncResponseStream *stream, climate::Clima climate_failed_row_(stream, obj, area, node, friendly_name, current_humidity, false); } } - if (traits.get_supports_target_humidity()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TARGET_HUMIDITY)) { std::string target_humidity = "target_humidity"; if (std::isnan(obj->target_humidity)) { climate_failed_row_(stream, obj, area, node, friendly_name, target_humidity, true); @@ -949,7 +949,8 @@ void PrometheusHandler::climate_row_(AsyncResponseStream *stream, climate::Clima climate_failed_row_(stream, obj, area, node, friendly_name, target_humidity, false); } } - if (traits.get_supports_two_point_target_temperature()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE | + climate::CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE)) { std::string target_temp_low = "target_temperature_low"; auto target_temp_low_value = value_accuracy_to_string(obj->target_temperature_low, target_accuracy); climate_value_row_(stream, obj, area, node, friendly_name, target_temp_low, target_temp_low_value); @@ -961,7 +962,7 @@ void PrometheusHandler::climate_row_(AsyncResponseStream *stream, climate::Clima auto target_temp_value = value_accuracy_to_string(obj->target_temperature, target_accuracy); climate_value_row_(stream, obj, area, node, friendly_name, target_temp, target_temp_value); } - if (traits.get_supports_action()) { + if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_ACTION)) { std::string climate_trait_category = "action"; const auto *climate_trait_value = climate::climate_action_to_string(obj->action); climate_setting_row_(stream, obj, area, node, friendly_name, climate_trait_category, climate_trait_value);