1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-31 23:21:54 +00:00
This commit is contained in:
J. Nick Koston
2025-10-30 19:37:02 -05:00
parent 1864cf6ad8
commit af165539e6
3 changed files with 32 additions and 20 deletions

View File

@@ -65,7 +65,13 @@ using ClimatePresetMask = FiniteSetMask<ClimatePreset, DefaultBitPolicy<ClimateP
* - temperature step - the step with which to increase/decrease target temperature.
* This also affects with how many decimal places the temperature is shown
*/
class Climate; // Forward declaration
class ClimateCall; // Forward declaration
class ClimateTraits {
friend class Climate; // Allow Climate to access protected find methods
friend class ClimateCall; // Allow ClimateCall to access protected find methods
public:
/// Get/set feature flags (see ClimateFeatures enum in climate_mode.h)
uint32_t get_feature_flags() const { return this->feature_flags_; }
@@ -160,10 +166,6 @@ class ClimateTraits {
bool supports_custom_fan_mode(const std::string &custom_fan_mode) const {
return this->supports_custom_fan_mode(custom_fan_mode.c_str());
}
/// Find and return the matching custom fan mode pointer from supported modes, or nullptr if not found
const char *find_custom_fan_mode(const char *custom_fan_mode) const {
return vector_find(this->supported_custom_fan_modes_, custom_fan_mode);
}
void set_supported_presets(ClimatePresetMask presets) { this->supported_presets_ = presets; }
void add_supported_preset(ClimatePreset preset) { this->supported_presets_.insert(preset); }
@@ -187,10 +189,6 @@ class ClimateTraits {
bool supports_custom_preset(const std::string &custom_preset) const {
return this->supports_custom_preset(custom_preset.c_str());
}
/// Find and return the matching custom preset pointer from supported presets, or nullptr if not found
const char *find_custom_preset(const char *custom_preset) const {
return vector_find(this->supported_custom_presets_, custom_preset);
}
void set_supported_swing_modes(ClimateSwingModeMask modes) { this->supported_swing_modes_ = modes; }
void add_supported_swing_mode(ClimateSwingMode mode) { this->supported_swing_modes_.insert(mode); }
@@ -249,6 +247,18 @@ class ClimateTraits {
}
}
/// Find and return the matching custom fan mode pointer from supported modes, or nullptr if not found
/// This is protected as it's an implementation detail - use Climate::set_custom_fan_mode_() instead
const char *find_custom_fan_mode(const char *custom_fan_mode) const {
return vector_find(this->supported_custom_fan_modes_, custom_fan_mode);
}
/// Find and return the matching custom preset pointer from supported presets, or nullptr if not found
/// This is protected as it's an implementation detail - use Climate::set_custom_preset_() instead
const char *find_custom_preset(const char *custom_preset) const {
return vector_find(this->supported_custom_presets_, custom_preset);
}
uint32_t feature_flags_{0};
float visual_min_temperature_{10};
float visual_max_temperature_{30};

View File

@@ -223,7 +223,8 @@ void ThermostatClimate::control(const climate::ClimateCall &call) {
if (this->setup_complete_) {
this->change_custom_preset_(call.get_custom_preset().value());
} else {
this->custom_preset = call.get_custom_preset().value();
// Use the base class method which handles pointer lookup internally
this->set_custom_preset_(call.get_custom_preset().value());
}
}
@@ -1171,7 +1172,7 @@ void ThermostatClimate::change_preset_(climate::ClimatePreset preset) {
} else {
ESP_LOGI(TAG, "No changes required to apply preset %s", LOG_STR_ARG(climate::climate_preset_to_string(preset)));
}
this->custom_preset.reset();
this->custom_preset = nullptr;
this->preset = preset;
} else {
ESP_LOGW(TAG, "Preset %s not configured; ignoring", LOG_STR_ARG(climate::climate_preset_to_string(preset)));
@@ -1183,11 +1184,12 @@ void ThermostatClimate::change_custom_preset_(const std::string &custom_preset)
if (config != this->custom_preset_config_.end()) {
ESP_LOGV(TAG, "Custom preset %s requested", custom_preset.c_str());
if (this->change_preset_internal_(config->second) || (!this->custom_preset.has_value()) ||
this->custom_preset.value() != custom_preset) {
if (this->change_preset_internal_(config->second) || (this->custom_preset == nullptr) ||
strcmp(this->custom_preset, custom_preset.c_str()) != 0) {
// Fire any preset changed trigger if defined
Trigger<> *trig = this->preset_change_trigger_;
this->custom_preset = custom_preset;
// Use the base class method which handles pointer lookup and preset reset internally
this->set_custom_preset_(custom_preset);
if (trig != nullptr) {
trig->trigger();
}
@@ -1196,9 +1198,9 @@ void ThermostatClimate::change_custom_preset_(const std::string &custom_preset)
ESP_LOGI(TAG, "Custom preset %s applied", custom_preset.c_str());
} else {
ESP_LOGI(TAG, "No changes required to apply custom preset %s", custom_preset.c_str());
// Still need to ensure preset is reset and custom_preset is set
this->set_custom_preset_(custom_preset);
}
this->preset.reset();
this->custom_preset = custom_preset;
} else {
ESP_LOGW(TAG, "Custom preset %s not configured; ignoring", custom_preset.c_str());
}

View File

@@ -1312,7 +1312,7 @@ std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_conf
for (climate::ClimatePreset m : traits.get_supported_presets())
opt.add(PSTR_LOCAL(climate::climate_preset_to_string(m)));
}
if (!traits.get_supported_custom_presets().empty() && obj->custom_preset.has_value()) {
if (!traits.get_supported_custom_presets().empty() && obj->custom_preset != nullptr) {
JsonArray opt = root["custom_presets"].to<JsonArray>();
for (auto const &custom_preset : traits.get_supported_custom_presets())
opt.add(custom_preset);
@@ -1333,14 +1333,14 @@ std::string WebServer::climate_json(climate::Climate *obj, JsonDetail start_conf
if (traits.get_supports_fan_modes() && obj->fan_mode.has_value()) {
root["fan_mode"] = PSTR_LOCAL(climate_fan_mode_to_string(obj->fan_mode.value()));
}
if (!traits.get_supported_custom_fan_modes().empty() && obj->custom_fan_mode.has_value()) {
root["custom_fan_mode"] = obj->custom_fan_mode.value().c_str();
if (!traits.get_supported_custom_fan_modes().empty() && obj->custom_fan_mode != nullptr) {
root["custom_fan_mode"] = obj->custom_fan_mode;
}
if (traits.get_supports_presets() && obj->preset.has_value()) {
root["preset"] = PSTR_LOCAL(climate_preset_to_string(obj->preset.value()));
}
if (!traits.get_supported_custom_presets().empty() && obj->custom_preset.has_value()) {
root["custom_preset"] = obj->custom_preset.value().c_str();
if (!traits.get_supported_custom_presets().empty() && obj->custom_preset != nullptr) {
root["custom_preset"] = obj->custom_preset;
}
if (traits.get_supports_swing_modes()) {
root["swing_mode"] = PSTR_LOCAL(climate_swing_mode_to_string(obj->swing_mode));