ESPHome 2025.12.2
Loading...
Searching...
No Matches
climate.cpp
Go to the documentation of this file.
1#include "climate.h"
5
6namespace esphome::climate {
7
8static const char *const TAG = "climate";
9
10// Memory-efficient lookup tables
11struct StringToUint8 {
12 const char *str;
13 const uint8_t value;
14};
15
16constexpr StringToUint8 CLIMATE_MODES_BY_STR[] = {
17 {"OFF", CLIMATE_MODE_OFF},
18 {"AUTO", CLIMATE_MODE_AUTO},
19 {"COOL", CLIMATE_MODE_COOL},
20 {"HEAT", CLIMATE_MODE_HEAT},
21 {"FAN_ONLY", CLIMATE_MODE_FAN_ONLY},
22 {"DRY", CLIMATE_MODE_DRY},
23 {"HEAT_COOL", CLIMATE_MODE_HEAT_COOL},
24};
25
26constexpr StringToUint8 CLIMATE_FAN_MODES_BY_STR[] = {
27 {"ON", CLIMATE_FAN_ON}, {"OFF", CLIMATE_FAN_OFF}, {"AUTO", CLIMATE_FAN_AUTO},
28 {"LOW", CLIMATE_FAN_LOW}, {"MEDIUM", CLIMATE_FAN_MEDIUM}, {"HIGH", CLIMATE_FAN_HIGH},
29 {"MIDDLE", CLIMATE_FAN_MIDDLE}, {"FOCUS", CLIMATE_FAN_FOCUS}, {"DIFFUSE", CLIMATE_FAN_DIFFUSE},
30 {"QUIET", CLIMATE_FAN_QUIET},
31};
32
33constexpr StringToUint8 CLIMATE_PRESETS_BY_STR[] = {
34 {"ECO", CLIMATE_PRESET_ECO}, {"AWAY", CLIMATE_PRESET_AWAY}, {"BOOST", CLIMATE_PRESET_BOOST},
35 {"COMFORT", CLIMATE_PRESET_COMFORT}, {"HOME", CLIMATE_PRESET_HOME}, {"SLEEP", CLIMATE_PRESET_SLEEP},
36 {"ACTIVITY", CLIMATE_PRESET_ACTIVITY}, {"NONE", CLIMATE_PRESET_NONE},
37};
38
39constexpr StringToUint8 CLIMATE_SWING_MODES_BY_STR[] = {
40 {"OFF", CLIMATE_SWING_OFF},
41 {"BOTH", CLIMATE_SWING_BOTH},
42 {"VERTICAL", CLIMATE_SWING_VERTICAL},
43 {"HORIZONTAL", CLIMATE_SWING_HORIZONTAL},
44};
45
47 this->parent_->control_callback_.call(*this);
48 ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
49 this->validate_();
50 if (this->mode_.has_value()) {
51 const LogString *mode_s = climate_mode_to_string(*this->mode_);
52 ESP_LOGD(TAG, " Mode: %s", LOG_STR_ARG(mode_s));
53 }
54 if (this->custom_fan_mode_ != nullptr) {
55 this->fan_mode_.reset();
56 ESP_LOGD(TAG, " Custom Fan: %s", this->custom_fan_mode_);
57 }
58 if (this->fan_mode_.has_value()) {
59 this->custom_fan_mode_ = nullptr;
60 const LogString *fan_mode_s = climate_fan_mode_to_string(*this->fan_mode_);
61 ESP_LOGD(TAG, " Fan: %s", LOG_STR_ARG(fan_mode_s));
62 }
63 if (this->custom_preset_ != nullptr) {
64 this->preset_.reset();
65 ESP_LOGD(TAG, " Custom Preset: %s", this->custom_preset_);
66 }
67 if (this->preset_.has_value()) {
68 this->custom_preset_ = nullptr;
69 const LogString *preset_s = climate_preset_to_string(*this->preset_);
70 ESP_LOGD(TAG, " Preset: %s", LOG_STR_ARG(preset_s));
71 }
72 if (this->swing_mode_.has_value()) {
73 const LogString *swing_mode_s = climate_swing_mode_to_string(*this->swing_mode_);
74 ESP_LOGD(TAG, " Swing: %s", LOG_STR_ARG(swing_mode_s));
75 }
76 if (this->target_temperature_.has_value()) {
77 ESP_LOGD(TAG, " Target Temperature: %.2f", *this->target_temperature_);
78 }
80 ESP_LOGD(TAG, " Target Temperature Low: %.2f", *this->target_temperature_low_);
81 }
83 ESP_LOGD(TAG, " Target Temperature High: %.2f", *this->target_temperature_high_);
84 }
85 if (this->target_humidity_.has_value()) {
86 ESP_LOGD(TAG, " Target Humidity: %.0f", *this->target_humidity_);
87 }
88 this->parent_->control(*this);
89}
90
92 auto traits = this->parent_->get_traits();
93 if (this->mode_.has_value()) {
94 auto mode = *this->mode_;
95 if (!traits.supports_mode(mode)) {
96 ESP_LOGW(TAG, " Mode %s not supported", LOG_STR_ARG(climate_mode_to_string(mode)));
97 this->mode_.reset();
98 }
99 }
100 if (this->custom_fan_mode_ != nullptr) {
101 if (!traits.supports_custom_fan_mode(this->custom_fan_mode_)) {
102 ESP_LOGW(TAG, " Fan Mode %s not supported", this->custom_fan_mode_);
103 this->custom_fan_mode_ = nullptr;
104 }
105 } else if (this->fan_mode_.has_value()) {
106 auto fan_mode = *this->fan_mode_;
107 if (!traits.supports_fan_mode(fan_mode)) {
108 ESP_LOGW(TAG, " Fan Mode %s not supported", LOG_STR_ARG(climate_fan_mode_to_string(fan_mode)));
109 this->fan_mode_.reset();
110 }
111 }
112 if (this->custom_preset_ != nullptr) {
113 if (!traits.supports_custom_preset(this->custom_preset_)) {
114 ESP_LOGW(TAG, " Preset %s not supported", this->custom_preset_);
115 this->custom_preset_ = nullptr;
116 }
117 } else if (this->preset_.has_value()) {
118 auto preset = *this->preset_;
119 if (!traits.supports_preset(preset)) {
120 ESP_LOGW(TAG, " Preset %s not supported", LOG_STR_ARG(climate_preset_to_string(preset)));
121 this->preset_.reset();
122 }
123 }
124 if (this->swing_mode_.has_value()) {
125 auto swing_mode = *this->swing_mode_;
126 if (!traits.supports_swing_mode(swing_mode)) {
127 ESP_LOGW(TAG, " Swing Mode %s not supported", LOG_STR_ARG(climate_swing_mode_to_string(swing_mode)));
128 this->swing_mode_.reset();
129 }
130 }
131 if (this->target_temperature_.has_value()) {
132 auto target = *this->target_temperature_;
133 if (traits.has_feature_flags(CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE |
135 ESP_LOGW(TAG, " Cannot set target temperature for climate device "
136 "with two-point target temperature");
138 } else if (std::isnan(target)) {
139 ESP_LOGW(TAG, " Target temperature must not be NAN");
141 }
142 }
143 if (this->target_temperature_low_.has_value() || this->target_temperature_high_.has_value()) {
144 if (!traits.has_feature_flags(CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE |
146 ESP_LOGW(TAG, " Cannot set low/high target temperature");
149 }
150 }
151 if (this->target_temperature_low_.has_value() && std::isnan(*this->target_temperature_low_)) {
152 ESP_LOGW(TAG, " Target temperature low must not be NAN");
154 }
155 if (this->target_temperature_high_.has_value() && std::isnan(*this->target_temperature_high_)) {
156 ESP_LOGW(TAG, " Target temperature high must not be NAN");
158 }
159 if (this->target_temperature_low_.has_value() && this->target_temperature_high_.has_value()) {
160 float low = *this->target_temperature_low_;
161 float high = *this->target_temperature_high_;
162 if (low > high) {
163 ESP_LOGW(TAG, " Target temperature low %.2f must be less than target temperature high %.2f", low, high);
166 }
167 }
168}
169
171 this->mode_ = mode;
172 return *this;
173}
174
176 for (const auto &mode_entry : CLIMATE_MODES_BY_STR) {
177 if (str_equals_case_insensitive(mode, mode_entry.str)) {
178 this->set_mode(static_cast<ClimateMode>(mode_entry.value));
179 return *this;
180 }
181 }
182 ESP_LOGW(TAG, "'%s' - Unrecognized mode %s", this->parent_->get_name().c_str(), mode.c_str());
183 return *this;
184}
185
187 this->fan_mode_ = fan_mode;
188 this->custom_fan_mode_ = nullptr;
189 return *this;
190}
191
193 // Check if it's a standard enum mode first
194 for (const auto &mode_entry : CLIMATE_FAN_MODES_BY_STR) {
195 if (str_equals_case_insensitive(custom_fan_mode, mode_entry.str)) {
196 return this->set_fan_mode(static_cast<ClimateFanMode>(mode_entry.value));
197 }
198 }
199 // Find the matching pointer from parent climate device
200 if (const char *mode_ptr = this->parent_->find_custom_fan_mode_(custom_fan_mode)) {
201 this->custom_fan_mode_ = mode_ptr;
202 this->fan_mode_.reset();
203 return *this;
204 }
205 ESP_LOGW(TAG, "'%s' - Unrecognized fan mode %s", this->parent_->get_name().c_str(), custom_fan_mode);
206 return *this;
207}
208
209ClimateCall &ClimateCall::set_fan_mode(const std::string &fan_mode) { return this->set_fan_mode(fan_mode.c_str()); }
210
212 if (fan_mode.has_value()) {
213 this->set_fan_mode(fan_mode.value());
214 }
215 return *this;
216}
217
219 this->preset_ = preset;
220 this->custom_preset_ = nullptr;
221 return *this;
222}
223
225 // Check if it's a standard enum preset first
226 for (const auto &preset_entry : CLIMATE_PRESETS_BY_STR) {
227 if (str_equals_case_insensitive(custom_preset, preset_entry.str)) {
228 return this->set_preset(static_cast<ClimatePreset>(preset_entry.value));
229 }
230 }
231 // Find the matching pointer from parent climate device
232 if (const char *preset_ptr = this->parent_->find_custom_preset_(custom_preset)) {
233 this->custom_preset_ = preset_ptr;
234 this->preset_.reset();
235 return *this;
236 }
237 ESP_LOGW(TAG, "'%s' - Unrecognized preset %s", this->parent_->get_name().c_str(), custom_preset);
238 return *this;
239}
240
241ClimateCall &ClimateCall::set_preset(const std::string &preset) { return this->set_preset(preset.c_str()); }
242
244 if (preset.has_value()) {
245 this->set_preset(preset.value());
246 }
247 return *this;
248}
249
254
256 for (const auto &mode_entry : CLIMATE_SWING_MODES_BY_STR) {
257 if (str_equals_case_insensitive(swing_mode, mode_entry.str)) {
258 this->set_swing_mode(static_cast<ClimateSwingMode>(mode_entry.value));
259 return *this;
260 }
261 }
262 ESP_LOGW(TAG, "'%s' - Unrecognized swing mode %s", this->parent_->get_name().c_str(), swing_mode.c_str());
263 return *this;
264}
265
270
275
280
285
290
291const optional<ClimateMode> &ClimateCall::get_mode() const { return this->mode_; }
295
300
305
310
315
320
322 this->fan_mode_ = fan_mode;
323 this->custom_fan_mode_ = nullptr;
324 return *this;
325}
326
328 this->preset_ = preset;
329 this->custom_preset_ = nullptr;
330 return *this;
331}
332
337
338void Climate::add_on_state_callback(std::function<void(Climate &)> &&callback) {
339 this->state_callback_.add(std::move(callback));
340}
341
342void Climate::add_on_control_callback(std::function<void(ClimateCall &)> &&callback) {
343 this->control_callback_.add(std::move(callback));
344}
345
346// Random 32bit value; If this changes existing restore preferences are invalidated
347static const uint32_t RESTORE_STATE_VERSION = 0x848EA6ADUL;
348
351 RESTORE_STATE_VERSION);
352 ClimateDeviceRestoreState recovered{};
353 if (!this->rtc_.load(&recovered))
354 return {};
355 return recovered;
356}
357
359#if (defined(USE_ESP_IDF) || (defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 0, 0))) && \
360 !defined(CLANG_TIDY)
361#pragma GCC diagnostic ignored "-Wclass-memaccess"
362#define TEMP_IGNORE_MEMACCESS
363#endif
365 // initialize as zero to prevent random data on stack triggering erase
366 memset(&state, 0, sizeof(ClimateDeviceRestoreState));
367#ifdef TEMP_IGNORE_MEMACCESS
368#pragma GCC diagnostic pop
369#undef TEMP_IGNORE_MEMACCESS
370#endif
371
372 state.mode = this->mode;
373 auto traits = this->get_traits();
376 state.target_temperature_low = this->target_temperature_low;
377 state.target_temperature_high = this->target_temperature_high;
378 } else {
379 state.target_temperature = this->target_temperature;
380 }
382 state.target_humidity = this->target_humidity;
383 }
385 state.uses_custom_fan_mode = false;
386 state.fan_mode = this->fan_mode.value();
387 }
388 if (!traits.get_supported_custom_fan_modes().empty() && this->has_custom_fan_mode()) {
389 state.uses_custom_fan_mode = true;
390 const auto &supported = traits.get_supported_custom_fan_modes();
391 // std::vector maintains insertion order
392 size_t i = 0;
393 for (const char *mode : supported) {
394 if (strcmp(mode, this->custom_fan_mode_) == 0) {
395 state.custom_fan_mode = i;
396 break;
397 }
398 i++;
399 }
400 }
402 state.uses_custom_preset = false;
403 state.preset = this->preset.value();
404 }
405 if (!traits.get_supported_custom_presets().empty() && this->has_custom_preset()) {
406 state.uses_custom_preset = true;
407 const auto &supported = traits.get_supported_custom_presets();
408 // std::vector maintains insertion order
409 size_t i = 0;
410 for (const char *preset : supported) {
411 if (strcmp(preset, this->custom_preset_) == 0) {
412 state.custom_preset = i;
413 break;
414 }
415 i++;
416 }
417 }
419 state.swing_mode = this->swing_mode;
420 }
421
422 this->rtc_.save(&state);
423}
424
426 ESP_LOGD(TAG, "'%s' - Sending state:", this->name_.c_str());
427 auto traits = this->get_traits();
428
429 ESP_LOGD(TAG, " Mode: %s", LOG_STR_ARG(climate_mode_to_string(this->mode)));
431 ESP_LOGD(TAG, " Action: %s", LOG_STR_ARG(climate_action_to_string(this->action)));
432 }
433 if (traits.get_supports_fan_modes() && this->fan_mode.has_value()) {
434 ESP_LOGD(TAG, " Fan Mode: %s", LOG_STR_ARG(climate_fan_mode_to_string(this->fan_mode.value())));
435 }
436 if (!traits.get_supported_custom_fan_modes().empty() && this->has_custom_fan_mode()) {
437 ESP_LOGD(TAG, " Custom Fan Mode: %s", this->custom_fan_mode_);
438 }
439 if (traits.get_supports_presets() && this->preset.has_value()) {
440 ESP_LOGD(TAG, " Preset: %s", LOG_STR_ARG(climate_preset_to_string(this->preset.value())));
441 }
442 if (!traits.get_supported_custom_presets().empty() && this->has_custom_preset()) {
443 ESP_LOGD(TAG, " Custom Preset: %s", this->custom_preset_);
444 }
446 ESP_LOGD(TAG, " Swing Mode: %s", LOG_STR_ARG(climate_swing_mode_to_string(this->swing_mode)));
447 }
449 ESP_LOGD(TAG, " Current Temperature: %.2f°C", this->current_temperature);
450 }
453 ESP_LOGD(TAG, " Target Temperature: Low: %.2f°C High: %.2f°C", this->target_temperature_low,
455 } else {
456 ESP_LOGD(TAG, " Target Temperature: %.2f°C", this->target_temperature);
457 }
459 ESP_LOGD(TAG, " Current Humidity: %.0f%%", this->current_humidity);
460 }
462 ESP_LOGD(TAG, " Target Humidity: %.0f%%", this->target_humidity);
463 }
464
465 // Send state to frontend
466 this->state_callback_.call(*this);
467#if defined(USE_CLIMATE) && defined(USE_CONTROLLER_REGISTRY)
469#endif
470 // Save state
471 this->save_state_();
472}
473
495
496void Climate::set_visual_min_temperature_override(float visual_min_temperature_override) {
497 this->visual_min_temperature_override_ = visual_min_temperature_override;
498}
499
500void Climate::set_visual_max_temperature_override(float visual_max_temperature_override) {
501 this->visual_max_temperature_override_ = visual_max_temperature_override;
502}
503
508
509void Climate::set_visual_min_humidity_override(float visual_min_humidity_override) {
510 this->visual_min_humidity_override_ = visual_min_humidity_override;
511}
512
513void Climate::set_visual_max_humidity_override(float visual_max_humidity_override) {
514 this->visual_max_humidity_override_ = visual_max_humidity_override;
515}
516
518
520 auto call = climate->make_call();
521 auto traits = climate->get_traits();
522 call.set_mode(this->mode);
523 if (traits.has_feature_flags(CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE |
525 call.set_target_temperature_low(this->target_temperature_low);
526 call.set_target_temperature_high(this->target_temperature_high);
527 } else {
528 call.set_target_temperature(this->target_temperature);
529 }
530 if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TARGET_HUMIDITY)) {
531 call.set_target_humidity(this->target_humidity);
532 }
533 if (this->uses_custom_fan_mode) {
534 if (this->custom_fan_mode < traits.get_supported_custom_fan_modes().size()) {
535 call.fan_mode_.reset();
536 call.custom_fan_mode_ = traits.get_supported_custom_fan_modes()[this->custom_fan_mode];
537 }
538 } else if (traits.supports_fan_mode(this->fan_mode)) {
539 call.set_fan_mode(this->fan_mode);
540 }
541 if (this->uses_custom_preset) {
542 if (this->custom_preset < traits.get_supported_custom_presets().size()) {
543 call.preset_.reset();
544 call.custom_preset_ = traits.get_supported_custom_presets()[this->custom_preset];
545 }
546 } else if (traits.supports_preset(this->preset)) {
547 call.set_preset(this->preset);
548 }
549 if (traits.supports_swing_mode(this->swing_mode)) {
550 call.set_swing_mode(this->swing_mode);
551 }
552 return call;
553}
554
556 auto traits = climate->get_traits();
557 climate->mode = this->mode;
558 if (traits.has_feature_flags(CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE |
562 } else {
563 climate->target_temperature = this->target_temperature;
564 }
565 if (traits.has_feature_flags(climate::CLIMATE_SUPPORTS_TARGET_HUMIDITY)) {
566 climate->target_humidity = this->target_humidity;
567 }
568 if (this->uses_custom_fan_mode) {
569 if (this->custom_fan_mode < traits.get_supported_custom_fan_modes().size()) {
570 climate->fan_mode.reset();
571 climate->custom_fan_mode_ = traits.get_supported_custom_fan_modes()[this->custom_fan_mode];
572 }
573 } else if (traits.supports_fan_mode(this->fan_mode)) {
574 climate->fan_mode = this->fan_mode;
575 climate->clear_custom_fan_mode_();
576 }
577 if (this->uses_custom_preset) {
578 if (this->custom_preset < traits.get_supported_custom_presets().size()) {
579 climate->preset.reset();
580 climate->custom_preset_ = traits.get_supported_custom_presets()[this->custom_preset];
581 }
582 } else if (traits.supports_preset(this->preset)) {
583 climate->preset = this->preset;
584 climate->clear_custom_preset_();
585 }
586 if (traits.supports_swing_mode(this->swing_mode)) {
587 climate->swing_mode = this->swing_mode;
588 }
589 climate->publish_state();
590}
591
611template<typename T> bool set_primary_mode(optional<T> &primary, const char *&custom_ptr, T value) {
612 // Clear the custom mode (mutual exclusion)
613 bool changed = custom_ptr != nullptr;
614 custom_ptr = nullptr;
615 // Set the primary mode
616 if (changed || !primary.has_value() || primary.value() != value) {
617 primary = value;
618 return true;
619 }
620 return false;
621}
622
644template<typename T>
645bool set_custom_mode(const char *&custom_ptr, optional<T> &primary, const char *found_ptr, bool has_custom) {
646 if (found_ptr != nullptr) {
647 // Clear the primary mode (mutual exclusion)
648 bool changed = primary.has_value();
649 primary.reset();
650 // Set the custom mode (pointer is validated by caller from traits)
651 if (changed || custom_ptr != found_ptr) {
652 custom_ptr = found_ptr;
653 return true;
654 }
655 return false;
656 }
657 // Mode not found in supported modes, clear it if currently set
658 if (has_custom) {
659 custom_ptr = nullptr;
660 return true;
661 }
662 return false;
663}
664
666 return set_primary_mode(this->fan_mode, this->custom_fan_mode_, mode);
667}
668
670 auto traits = this->get_traits();
671 return set_custom_mode<ClimateFanMode>(this->custom_fan_mode_, this->fan_mode, traits.find_custom_fan_mode_(mode),
672 this->has_custom_fan_mode());
673}
674
675void Climate::clear_custom_fan_mode_() { this->custom_fan_mode_ = nullptr; }
676
677bool Climate::set_preset_(ClimatePreset preset) { return set_primary_mode(this->preset, this->custom_preset_, preset); }
678
680 auto traits = this->get_traits();
681 return set_custom_mode<ClimatePreset>(this->custom_preset_, this->preset, traits.find_custom_preset_(preset),
682 this->has_custom_preset());
683}
684
685void Climate::clear_custom_preset_() { this->custom_preset_ = nullptr; }
686
688 return this->get_traits().find_custom_fan_mode_(custom_fan_mode);
689}
690
692 return this->get_traits().find_custom_preset_(custom_preset);
693}
694
695void Climate::dump_traits_(const char *tag) {
696 auto traits = this->get_traits();
697 ESP_LOGCONFIG(tag, "ClimateTraits:");
698 ESP_LOGCONFIG(tag,
699 " Visual settings:\n"
700 " - Min temperature: %.1f\n"
701 " - Max temperature: %.1f\n"
702 " - Temperature step:\n"
703 " Target: %.1f",
707 ESP_LOGCONFIG(tag, " Current: %.1f", traits.get_visual_current_temperature_step());
708 }
711 ESP_LOGCONFIG(tag,
712 " - Min humidity: %.0f\n"
713 " - Max humidity: %.0f",
715 }
718 ESP_LOGCONFIG(tag, " Supports two-point target temperature");
719 }
721 ESP_LOGCONFIG(tag, " Supports current temperature");
722 }
724 ESP_LOGCONFIG(tag, " Supports target humidity");
725 }
727 ESP_LOGCONFIG(tag, " Supports current humidity");
728 }
730 ESP_LOGCONFIG(tag, " Supports action");
731 }
733 ESP_LOGCONFIG(tag, " Supported modes:");
735 ESP_LOGCONFIG(tag, " - %s", LOG_STR_ARG(climate_mode_to_string(m)));
736 }
738 ESP_LOGCONFIG(tag, " Supported fan modes:");
740 ESP_LOGCONFIG(tag, " - %s", LOG_STR_ARG(climate_fan_mode_to_string(m)));
741 }
742 if (!traits.get_supported_custom_fan_modes().empty()) {
743 ESP_LOGCONFIG(tag, " Supported custom fan modes:");
744 for (const char *s : traits.get_supported_custom_fan_modes())
745 ESP_LOGCONFIG(tag, " - %s", s);
746 }
748 ESP_LOGCONFIG(tag, " Supported presets:");
750 ESP_LOGCONFIG(tag, " - %s", LOG_STR_ARG(climate_preset_to_string(p)));
751 }
752 if (!traits.get_supported_custom_presets().empty()) {
753 ESP_LOGCONFIG(tag, " Supported custom presets:");
754 for (const char *s : traits.get_supported_custom_presets())
755 ESP_LOGCONFIG(tag, " - %s", s);
756 }
758 ESP_LOGCONFIG(tag, " Supported swing modes:");
760 ESP_LOGCONFIG(tag, " - %s", LOG_STR_ARG(climate_swing_mode_to_string(m)));
761 }
762}
763
764} // namespace esphome::climate
BedjetMode mode
BedJet operating mode.
uint8_t m
Definition bl0906.h:1
static void notify_climate_update(climate::Climate *obj)
bool save(const T *src)
Definition preferences.h:21
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
const StringRef & get_name() const
uint32_t get_preference_hash()
Get a unique hash for storing preferences/settings for this entity.
constexpr bool empty() const
Check if the set is empty.
constexpr const char * c_str() const
Definition string_ref.h:69
This class is used to encode all control actions on a climate device.
Definition climate.h:32
const optional< ClimateSwingMode > & get_swing_mode() const
Definition climate.cpp:293
optional< float > target_temperature_high_
Definition climate.h:120
const optional< float > & get_target_humidity() const
Definition climate.cpp:289
ClimateCall & set_target_temperature(float target_temperature)
Set the target temperature of the climate device.
Definition climate.cpp:266
const optional< float > & get_target_temperature_low() const
Definition climate.cpp:287
ClimateCall & set_swing_mode(ClimateSwingMode swing_mode)
Set the swing mode of the climate device.
Definition climate.cpp:250
optional< ClimateFanMode > fan_mode_
Definition climate.h:123
ClimateCall & set_target_temperature_low(float target_temperature_low)
Set the low point target temperature of the climate device.
Definition climate.cpp:271
optional< float > target_temperature_
Definition climate.h:118
const optional< float > & get_target_temperature() const
Definition climate.cpp:286
const optional< ClimatePreset > & get_preset() const
Definition climate.cpp:294
optional< ClimateSwingMode > swing_mode_
Definition climate.h:124
optional< ClimateMode > mode_
Definition climate.h:122
ClimateCall & set_preset(ClimatePreset preset)
Set the preset of the climate device.
Definition climate.cpp:218
const optional< float > & get_target_temperature_high() const
Definition climate.cpp:288
const optional< ClimateFanMode > & get_fan_mode() const
Definition climate.cpp:292
optional< float > target_humidity_
Definition climate.h:121
ClimateCall & set_fan_mode(ClimateFanMode fan_mode)
Set the fan mode of the climate device.
Definition climate.cpp:186
optional< ClimatePreset > preset_
Definition climate.h:125
ClimateCall & set_target_humidity(float target_humidity)
Set the target humidity of the climate device.
Definition climate.cpp:281
optional< float > target_temperature_low_
Definition climate.h:119
ClimateCall & set_target_temperature_high(float target_temperature_high)
Set the high point target temperature of the climate device.
Definition climate.cpp:276
ClimateCall & set_mode(ClimateMode mode)
Set the mode of the climate device.
Definition climate.cpp:170
const optional< ClimateMode > & get_mode() const
Definition climate.cpp:291
ClimateDevice - This is the base class for all climate integrations.
Definition climate.h:177
ClimateMode mode
The active mode of the climate device.
Definition climate.h:255
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition climate.h:249
optional< float > visual_max_humidity_override_
Definition climate.h:329
ClimateTraits get_traits()
Get the traits of this climate device with all overrides applied.
Definition climate.cpp:474
float target_temperature
The target temperature of the climate device.
Definition climate.h:236
float current_humidity
The current humidity of the climate device, as reported from the integration.
Definition climate.h:232
void set_visual_min_humidity_override(float visual_min_humidity_override)
Definition climate.cpp:509
optional< float > visual_current_temperature_step_override_
Definition climate.h:327
void dump_traits_(const char *tag)
Definition climate.cpp:695
CallbackManager< void(ClimateCall &)> control_callback_
Definition climate.h:322
CallbackManager< void(Climate &)> state_callback_
Definition climate.h:321
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition climate.h:261
optional< float > visual_target_temperature_step_override_
Definition climate.h:326
void save_state_()
Internal method to save the state of the climate device to recover memory.
Definition climate.cpp:358
float target_temperature_low
The minimum target temperature of the climate device, for climate devices with split target temperatu...
Definition climate.h:239
void set_visual_max_humidity_override(float visual_max_humidity_override)
Definition climate.cpp:513
void add_on_state_callback(std::function< void(Climate &)> &&callback)
Add a callback for the climate device state, each time the state of the climate device is updated (us...
Definition climate.cpp:338
virtual ClimateTraits traits()=0
Get the default traits of this climate device.
bool set_preset_(ClimatePreset preset)
Set preset. Reset custom preset. Return true if preset has been changed.
Definition climate.cpp:677
bool set_custom_preset_(const char *preset)
Set custom preset. Reset primary preset. Return true if preset has been changed.
Definition climate.cpp:679
const char * find_custom_fan_mode_(const char *custom_fan_mode)
Find and return the matching custom fan mode pointer from traits, or nullptr if not found.
Definition climate.cpp:687
void set_visual_max_temperature_override(float visual_max_temperature_override)
Definition climate.cpp:500
optional< float > visual_min_humidity_override_
Definition climate.h:328
void clear_custom_preset_()
Clear custom preset.
Definition climate.cpp:685
optional< float > visual_max_temperature_override_
Definition climate.h:325
bool set_fan_mode_(ClimateFanMode mode)
Set fan mode. Reset custom fan mode. Return true if fan mode has been changed.
Definition climate.cpp:665
optional< float > visual_min_temperature_override_
Definition climate.h:324
const char * find_custom_preset_(const char *custom_preset)
Find and return the matching custom preset pointer from traits, or nullptr if not found.
Definition climate.cpp:691
void clear_custom_fan_mode_()
Clear custom fan mode.
Definition climate.cpp:675
void add_on_control_callback(std::function< void(ClimateCall &)> &&callback)
Add a callback for the climate device configuration; each time the configuration parameters of a clim...
Definition climate.cpp:342
float current_temperature
The current temperature of the climate device, as reported from the integration.
Definition climate.h:229
ClimateAction action
The active state of the climate device.
Definition climate.h:258
ClimateCall make_call()
Make a climate device control call, this is used to control the climate device, see the ClimateCall d...
Definition climate.cpp:517
virtual void control(const ClimateCall &call)=0
Control the climate device, this is a virtual method that each climate integration must implement.
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition climate.cpp:425
void set_visual_temperature_step_override(float target, float current)
Definition climate.cpp:504
ESPPreferenceObject rtc_
Definition climate.h:323
optional< ClimatePreset > preset
The active preset of the climate device.
Definition climate.h:252
void set_visual_min_temperature_override(float visual_min_temperature_override)
Definition climate.cpp:496
optional< ClimateDeviceRestoreState > restore_state_()
Restore the state of the climate device, call this from your setup() method.
Definition climate.cpp:349
float target_humidity
The target humidity of the climate device.
Definition climate.h:246
bool set_custom_fan_mode_(const char *mode)
Set custom fan mode. Reset primary fan mode. Return true if fan mode has been changed.
Definition climate.cpp:669
float target_temperature_high
The maximum target temperature of the climate device, for climate devices with split target temperatu...
Definition climate.h:241
void set_visual_max_temperature(float visual_max_temperature)
const ClimatePresetMask & get_supported_presets() const
const std::vector< const char * > & get_supported_custom_fan_modes() const
const ClimateSwingModeMask & get_supported_swing_modes() const
void set_visual_target_temperature_step(float temperature_step)
float get_visual_current_temperature_step() const
void set_visual_min_temperature(float visual_min_temperature)
const ClimateFanModeMask & get_supported_fan_modes() const
float get_visual_target_temperature_step() const
void set_visual_min_humidity(float visual_min_humidity)
void set_visual_current_temperature_step(float temperature_step)
bool has_feature_flags(uint32_t feature_flags) const
void set_visual_max_humidity(float visual_max_humidity)
const char * find_custom_fan_mode_(const char *custom_fan_mode) const
Find and return the matching custom fan mode pointer from supported modes, or nullptr if not found Th...
const char * find_custom_preset_(const char *custom_preset) const
Find and return the matching custom preset pointer from supported presets, or nullptr if not found Th...
const std::vector< const char * > & get_supported_custom_presets() const
const ClimateModeMask & get_supported_modes() const
bool has_value() const
Definition optional.h:92
value_type const & value() const
Definition optional.h:94
float target_temperature_high
Definition climate.h:3
float target_humidity
Definition climate.h:19
ClimateSwingMode swing_mode
Definition climate.h:11
float target_temperature
Definition climate.h:0
uint8_t custom_preset
Definition climate.h:9
ClimateFanMode fan_mode
Definition climate.h:3
ClimatePreset preset
Definition climate.h:8
float target_temperature_low
Definition climate.h:2
uint8_t custom_fan_mode
Definition climate.h:4
bool state
Definition fan.h:0
const LogString * climate_action_to_string(ClimateAction action)
Convert the given ClimateAction to a human-readable string.
constexpr StringToUint8 CLIMATE_MODES_BY_STR[]
Definition climate.cpp:16
@ CLIMATE_SUPPORTS_CURRENT_HUMIDITY
@ CLIMATE_SUPPORTS_TWO_POINT_TARGET_TEMPERATURE
@ CLIMATE_SUPPORTS_CURRENT_TEMPERATURE
@ CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE
const LogString * climate_swing_mode_to_string(ClimateSwingMode swing_mode)
Convert the given ClimateSwingMode to a human-readable string.
constexpr StringToUint8 CLIMATE_PRESETS_BY_STR[]
Definition climate.cpp:33
const LogString * climate_preset_to_string(ClimatePreset preset)
Convert the given PresetMode to a human-readable string.
ClimatePreset
Enum for all preset modes NOTE: If adding values, update ClimatePresetMask in climate_traits....
@ CLIMATE_PRESET_NONE
No preset is active.
@ CLIMATE_PRESET_COMFORT
Device is in comfort preset.
@ CLIMATE_PRESET_AWAY
Device is in away preset.
@ CLIMATE_PRESET_BOOST
Device is in boost preset.
@ CLIMATE_PRESET_ACTIVITY
Device is reacting to activity (e.g., movement sensors)
@ CLIMATE_PRESET_SLEEP
Device is prepared for sleep.
@ CLIMATE_PRESET_HOME
Device is in home preset.
@ CLIMATE_PRESET_ECO
Device is running an energy-saving preset.
const LogString * climate_fan_mode_to_string(ClimateFanMode fan_mode)
Convert the given ClimateFanMode to a human-readable string.
constexpr StringToUint8 CLIMATE_FAN_MODES_BY_STR[]
Definition climate.cpp:26
ClimateSwingMode
Enum for all modes a climate swing can be in NOTE: If adding values, update ClimateSwingModeMask in c...
@ CLIMATE_SWING_OFF
The swing mode is set to Off.
@ CLIMATE_SWING_HORIZONTAL
The fan mode is set to Horizontal.
@ CLIMATE_SWING_VERTICAL
The fan mode is set to Vertical.
@ CLIMATE_SWING_BOTH
The fan mode is set to Both.
ClimateMode
Enum for all modes a climate device can be in.
@ CLIMATE_MODE_DRY
The climate device is set to dry/humidity mode.
@ CLIMATE_MODE_FAN_ONLY
The climate device only has the fan enabled, no heating or cooling is taking place.
@ CLIMATE_MODE_HEAT
The climate device is set to heat to reach the target temperature.
@ CLIMATE_MODE_COOL
The climate device is set to cool to reach the target temperature.
@ CLIMATE_MODE_HEAT_COOL
The climate device is set to heat/cool to reach the target temperature.
@ CLIMATE_MODE_OFF
The climate device is off.
@ CLIMATE_MODE_AUTO
The climate device is adjusting the temperature dynamically.
const LogString * climate_mode_to_string(ClimateMode mode)
Convert the given ClimateMode to a human-readable string.
bool set_primary_mode(optional< T > &primary, const char *&custom_ptr, T value)
Template helper for setting primary modes (fan_mode, preset) with mutual exclusion.
Definition climate.cpp:611
constexpr StringToUint8 CLIMATE_SWING_MODES_BY_STR[]
Definition climate.cpp:39
bool set_custom_mode(const char *&custom_ptr, optional< T > &primary, const char *found_ptr, bool has_custom)
Template helper for setting custom modes (custom_fan_mode_, custom_preset_) with mutual exclusion.
Definition climate.cpp:645
ClimateFanMode
NOTE: If adding values, update ClimateFanModeMask in climate_traits.h to use the new last value.
@ CLIMATE_FAN_MEDIUM
The fan mode is set to Medium.
@ CLIMATE_FAN_DIFFUSE
The fan mode is set to Diffuse.
@ CLIMATE_FAN_ON
The fan mode is set to On.
@ CLIMATE_FAN_AUTO
The fan mode is set to Auto.
@ CLIMATE_FAN_FOCUS
The fan mode is set to Focus.
@ CLIMATE_FAN_LOW
The fan mode is set to Low.
@ CLIMATE_FAN_MIDDLE
The fan mode is set to Middle.
@ CLIMATE_FAN_QUIET
The fan mode is set to Quiet.
@ CLIMATE_FAN_OFF
The fan mode is set to Off.
@ CLIMATE_FAN_HIGH
The fan mode is set to High.
ESPPreferences * global_preferences
bool str_equals_case_insensitive(const std::string &a, const std::string &b)
Compare strings for equality in case-insensitive manner.
Definition helpers.cpp:161
Struct used to save the state of the climate device in restore memory.
Definition climate.h:134
ClimateCall to_call(Climate *climate)
Convert this struct to a climate call that can be performed.
Definition climate.cpp:519
void apply(Climate *climate)
Apply these settings to the climate device.
Definition climate.cpp:555