ESPHome  2024.12.2
climate.cpp
Go to the documentation of this file.
1 #include "climate.h"
2 #include "esphome/core/macros.h"
3 
4 namespace esphome {
5 namespace climate {
6 
7 static const char *const TAG = "climate";
8 
10  this->parent_->control_callback_.call(*this);
11  ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
12  this->validate_();
13  if (this->mode_.has_value()) {
14  const LogString *mode_s = climate_mode_to_string(*this->mode_);
15  ESP_LOGD(TAG, " Mode: %s", LOG_STR_ARG(mode_s));
16  }
17  if (this->custom_fan_mode_.has_value()) {
18  this->fan_mode_.reset();
19  ESP_LOGD(TAG, " Custom Fan: %s", this->custom_fan_mode_.value().c_str());
20  }
21  if (this->fan_mode_.has_value()) {
22  this->custom_fan_mode_.reset();
23  const LogString *fan_mode_s = climate_fan_mode_to_string(*this->fan_mode_);
24  ESP_LOGD(TAG, " Fan: %s", LOG_STR_ARG(fan_mode_s));
25  }
26  if (this->custom_preset_.has_value()) {
27  this->preset_.reset();
28  ESP_LOGD(TAG, " Custom Preset: %s", this->custom_preset_.value().c_str());
29  }
30  if (this->preset_.has_value()) {
31  this->custom_preset_.reset();
32  const LogString *preset_s = climate_preset_to_string(*this->preset_);
33  ESP_LOGD(TAG, " Preset: %s", LOG_STR_ARG(preset_s));
34  }
35  if (this->swing_mode_.has_value()) {
36  const LogString *swing_mode_s = climate_swing_mode_to_string(*this->swing_mode_);
37  ESP_LOGD(TAG, " Swing: %s", LOG_STR_ARG(swing_mode_s));
38  }
39  if (this->target_temperature_.has_value()) {
40  ESP_LOGD(TAG, " Target Temperature: %.2f", *this->target_temperature_);
41  }
42  if (this->target_temperature_low_.has_value()) {
43  ESP_LOGD(TAG, " Target Temperature Low: %.2f", *this->target_temperature_low_);
44  }
45  if (this->target_temperature_high_.has_value()) {
46  ESP_LOGD(TAG, " Target Temperature High: %.2f", *this->target_temperature_high_);
47  }
48  if (this->target_humidity_.has_value()) {
49  ESP_LOGD(TAG, " Target Humidity: %.0f", *this->target_humidity_);
50  }
51  this->parent_->control(*this);
52 }
54  auto traits = this->parent_->get_traits();
55  if (this->mode_.has_value()) {
56  auto mode = *this->mode_;
57  if (!traits.supports_mode(mode)) {
58  ESP_LOGW(TAG, " Mode %s is not supported by this device!", LOG_STR_ARG(climate_mode_to_string(mode)));
59  this->mode_.reset();
60  }
61  }
62  if (this->custom_fan_mode_.has_value()) {
63  auto custom_fan_mode = *this->custom_fan_mode_;
64  if (!traits.supports_custom_fan_mode(custom_fan_mode)) {
65  ESP_LOGW(TAG, " Fan Mode %s is not supported by this device!", custom_fan_mode.c_str());
66  this->custom_fan_mode_.reset();
67  }
68  } else if (this->fan_mode_.has_value()) {
69  auto fan_mode = *this->fan_mode_;
70  if (!traits.supports_fan_mode(fan_mode)) {
71  ESP_LOGW(TAG, " Fan Mode %s is not supported by this device!",
72  LOG_STR_ARG(climate_fan_mode_to_string(fan_mode)));
73  this->fan_mode_.reset();
74  }
75  }
76  if (this->custom_preset_.has_value()) {
77  auto custom_preset = *this->custom_preset_;
78  if (!traits.supports_custom_preset(custom_preset)) {
79  ESP_LOGW(TAG, " Preset %s is not supported by this device!", custom_preset.c_str());
80  this->custom_preset_.reset();
81  }
82  } else if (this->preset_.has_value()) {
83  auto preset = *this->preset_;
84  if (!traits.supports_preset(preset)) {
85  ESP_LOGW(TAG, " Preset %s is not supported by this device!", LOG_STR_ARG(climate_preset_to_string(preset)));
86  this->preset_.reset();
87  }
88  }
89  if (this->swing_mode_.has_value()) {
90  auto swing_mode = *this->swing_mode_;
91  if (!traits.supports_swing_mode(swing_mode)) {
92  ESP_LOGW(TAG, " Swing Mode %s is not supported by this device!",
94  this->swing_mode_.reset();
95  }
96  }
97  if (this->target_temperature_.has_value()) {
98  auto target = *this->target_temperature_;
99  if (traits.get_supports_two_point_target_temperature()) {
100  ESP_LOGW(TAG, " Cannot set target temperature for climate device "
101  "with two-point target temperature!");
102  this->target_temperature_.reset();
103  } else if (std::isnan(target)) {
104  ESP_LOGW(TAG, " Target temperature must not be NAN!");
105  this->target_temperature_.reset();
106  }
107  }
109  if (!traits.get_supports_two_point_target_temperature()) {
110  ESP_LOGW(TAG, " Cannot set low/high target temperature for this device!");
113  }
114  }
115  if (this->target_temperature_low_.has_value() && std::isnan(*this->target_temperature_low_)) {
116  ESP_LOGW(TAG, " Target temperature low must not be NAN!");
118  }
119  if (this->target_temperature_high_.has_value() && std::isnan(*this->target_temperature_high_)) {
120  ESP_LOGW(TAG, " Target temperature low must not be NAN!");
122  }
124  float low = *this->target_temperature_low_;
125  float high = *this->target_temperature_high_;
126  if (low > high) {
127  ESP_LOGW(TAG, " Target temperature low %.2f must be smaller than target temperature high %.2f!", low, high);
130  }
131  }
132 }
134  this->mode_ = mode;
135  return *this;
136 }
137 ClimateCall &ClimateCall::set_mode(const std::string &mode) {
138  if (str_equals_case_insensitive(mode, "OFF")) {
139  this->set_mode(CLIMATE_MODE_OFF);
140  } else if (str_equals_case_insensitive(mode, "AUTO")) {
142  } else if (str_equals_case_insensitive(mode, "COOL")) {
144  } else if (str_equals_case_insensitive(mode, "HEAT")) {
146  } else if (str_equals_case_insensitive(mode, "FAN_ONLY")) {
148  } else if (str_equals_case_insensitive(mode, "DRY")) {
149  this->set_mode(CLIMATE_MODE_DRY);
150  } else if (str_equals_case_insensitive(mode, "HEAT_COOL")) {
152  } else {
153  ESP_LOGW(TAG, "'%s' - Unrecognized mode %s", this->parent_->get_name().c_str(), mode.c_str());
154  }
155  return *this;
156 }
158  this->fan_mode_ = fan_mode;
159  this->custom_fan_mode_.reset();
160  return *this;
161 }
163  if (str_equals_case_insensitive(fan_mode, "ON")) {
165  } else if (str_equals_case_insensitive(fan_mode, "OFF")) {
167  } else if (str_equals_case_insensitive(fan_mode, "AUTO")) {
169  } else if (str_equals_case_insensitive(fan_mode, "LOW")) {
171  } else if (str_equals_case_insensitive(fan_mode, "MEDIUM")) {
173  } else if (str_equals_case_insensitive(fan_mode, "HIGH")) {
175  } else if (str_equals_case_insensitive(fan_mode, "MIDDLE")) {
177  } else if (str_equals_case_insensitive(fan_mode, "FOCUS")) {
179  } else if (str_equals_case_insensitive(fan_mode, "DIFFUSE")) {
181  } else if (str_equals_case_insensitive(fan_mode, "QUIET")) {
183  } else {
184  if (this->parent_->get_traits().supports_custom_fan_mode(fan_mode)) {
185  this->custom_fan_mode_ = fan_mode;
186  this->fan_mode_.reset();
187  } else {
188  ESP_LOGW(TAG, "'%s' - Unrecognized fan mode %s", this->parent_->get_name().c_str(), fan_mode.c_str());
189  }
190  }
191  return *this;
192 }
194  if (fan_mode.has_value()) {
195  this->set_fan_mode(fan_mode.value());
196  }
197  return *this;
198 }
200  this->preset_ = preset;
201  this->custom_preset_.reset();
202  return *this;
203 }
205  if (str_equals_case_insensitive(preset, "ECO")) {
207  } else if (str_equals_case_insensitive(preset, "AWAY")) {
209  } else if (str_equals_case_insensitive(preset, "BOOST")) {
211  } else if (str_equals_case_insensitive(preset, "COMFORT")) {
213  } else if (str_equals_case_insensitive(preset, "HOME")) {
215  } else if (str_equals_case_insensitive(preset, "SLEEP")) {
217  } else if (str_equals_case_insensitive(preset, "ACTIVITY")) {
219  } else if (str_equals_case_insensitive(preset, "NONE")) {
221  } else {
222  if (this->parent_->get_traits().supports_custom_preset(preset)) {
223  this->custom_preset_ = preset;
224  this->preset_.reset();
225  } else {
226  ESP_LOGW(TAG, "'%s' - Unrecognized preset %s", this->parent_->get_name().c_str(), preset.c_str());
227  }
228  }
229  return *this;
230 }
232  if (preset.has_value()) {
233  this->set_preset(preset.value());
234  }
235  return *this;
236 }
238  this->swing_mode_ = swing_mode;
239  return *this;
240 }
242  if (str_equals_case_insensitive(swing_mode, "OFF")) {
244  } else if (str_equals_case_insensitive(swing_mode, "BOTH")) {
246  } else if (str_equals_case_insensitive(swing_mode, "VERTICAL")) {
248  } else if (str_equals_case_insensitive(swing_mode, "HORIZONTAL")) {
250  } else {
251  ESP_LOGW(TAG, "'%s' - Unrecognized swing mode %s", this->parent_->get_name().c_str(), swing_mode.c_str());
252  }
253  return *this;
254 }
255 
258  return *this;
259 }
262  return *this;
263 }
266  return *this;
267 }
270  return *this;
271 }
272 
273 const optional<ClimateMode> &ClimateCall::get_mode() const { return this->mode_; }
285  return *this;
286 }
289  return *this;
290 }
293  return *this;
294 }
297  return *this;
298 }
300  this->mode_ = mode;
301  return *this;
302 }
304  this->fan_mode_ = fan_mode;
305  this->custom_fan_mode_.reset();
306  return *this;
307 }
309  this->preset_ = preset;
310  this->custom_preset_.reset();
311  return *this;
312 }
314  this->swing_mode_ = swing_mode;
315  return *this;
316 }
317 
318 void Climate::add_on_state_callback(std::function<void(Climate &)> &&callback) {
319  this->state_callback_.add(std::move(callback));
320 }
321 
322 void Climate::add_on_control_callback(std::function<void(ClimateCall &)> &&callback) {
323  this->control_callback_.add(std::move(callback));
324 }
325 
326 // Random 32bit value; If this changes existing restore preferences are invalidated
327 static const uint32_t RESTORE_STATE_VERSION = 0x848EA6ADUL;
328 
330  this->rtc_ = global_preferences->make_preference<ClimateDeviceRestoreState>(this->get_object_id_hash() ^
331  RESTORE_STATE_VERSION);
332  ClimateDeviceRestoreState recovered{};
333  if (!this->rtc_.load(&recovered))
334  return {};
335  return recovered;
336 }
338 #if (defined(USE_ESP_IDF) || (defined(USE_ESP8266) && USE_ARDUINO_VERSION_CODE >= VERSION_CODE(3, 0, 0))) && \
339  !defined(CLANG_TIDY)
340 #pragma GCC diagnostic ignored "-Wclass-memaccess"
341 #define TEMP_IGNORE_MEMACCESS
342 #endif
344  // initialize as zero to prevent random data on stack triggering erase
345  memset(&state, 0, sizeof(ClimateDeviceRestoreState));
346 #ifdef TEMP_IGNORE_MEMACCESS
347 #pragma GCC diagnostic pop
348 #undef TEMP_IGNORE_MEMACCESS
349 #endif
350 
351  state.mode = this->mode;
352  auto traits = this->get_traits();
353  if (traits.get_supports_two_point_target_temperature()) {
354  state.target_temperature_low = this->target_temperature_low;
355  state.target_temperature_high = this->target_temperature_high;
356  } else {
357  state.target_temperature = this->target_temperature;
358  }
359  if (traits.get_supports_target_humidity()) {
360  state.target_humidity = this->target_humidity;
361  }
362  if (traits.get_supports_fan_modes() && fan_mode.has_value()) {
363  state.uses_custom_fan_mode = false;
364  state.fan_mode = this->fan_mode.value();
365  }
366  if (!traits.get_supported_custom_fan_modes().empty() && custom_fan_mode.has_value()) {
367  state.uses_custom_fan_mode = true;
368  const auto &supported = traits.get_supported_custom_fan_modes();
369  std::vector<std::string> vec{supported.begin(), supported.end()};
370  auto it = std::find(vec.begin(), vec.end(), custom_fan_mode);
371  if (it != vec.end()) {
372  state.custom_fan_mode = std::distance(vec.begin(), it);
373  }
374  }
375  if (traits.get_supports_presets() && preset.has_value()) {
376  state.uses_custom_preset = false;
377  state.preset = this->preset.value();
378  }
379  if (!traits.get_supported_custom_presets().empty() && custom_preset.has_value()) {
380  state.uses_custom_preset = true;
381  const auto &supported = traits.get_supported_custom_presets();
382  std::vector<std::string> vec{supported.begin(), supported.end()};
383  auto it = std::find(vec.begin(), vec.end(), custom_preset);
384  // only set custom preset if value exists, otherwise leave it as is
385  if (it != vec.cend()) {
386  state.custom_preset = std::distance(vec.begin(), it);
387  }
388  }
389  if (traits.get_supports_swing_modes()) {
390  state.swing_mode = this->swing_mode;
391  }
392 
393  this->rtc_.save(&state);
394 }
396  ESP_LOGD(TAG, "'%s' - Sending state:", this->name_.c_str());
397  auto traits = this->get_traits();
398 
399  ESP_LOGD(TAG, " Mode: %s", LOG_STR_ARG(climate_mode_to_string(this->mode)));
400  if (traits.get_supports_action()) {
401  ESP_LOGD(TAG, " Action: %s", LOG_STR_ARG(climate_action_to_string(this->action)));
402  }
403  if (traits.get_supports_fan_modes() && this->fan_mode.has_value()) {
404  ESP_LOGD(TAG, " Fan Mode: %s", LOG_STR_ARG(climate_fan_mode_to_string(this->fan_mode.value())));
405  }
406  if (!traits.get_supported_custom_fan_modes().empty() && this->custom_fan_mode.has_value()) {
407  ESP_LOGD(TAG, " Custom Fan Mode: %s", this->custom_fan_mode.value().c_str());
408  }
409  if (traits.get_supports_presets() && this->preset.has_value()) {
410  ESP_LOGD(TAG, " Preset: %s", LOG_STR_ARG(climate_preset_to_string(this->preset.value())));
411  }
412  if (!traits.get_supported_custom_presets().empty() && this->custom_preset.has_value()) {
413  ESP_LOGD(TAG, " Custom Preset: %s", this->custom_preset.value().c_str());
414  }
415  if (traits.get_supports_swing_modes()) {
416  ESP_LOGD(TAG, " Swing Mode: %s", LOG_STR_ARG(climate_swing_mode_to_string(this->swing_mode)));
417  }
418  if (traits.get_supports_current_temperature()) {
419  ESP_LOGD(TAG, " Current Temperature: %.2f°C", this->current_temperature);
420  }
421  if (traits.get_supports_two_point_target_temperature()) {
422  ESP_LOGD(TAG, " Target Temperature: Low: %.2f°C High: %.2f°C", this->target_temperature_low,
424  } else {
425  ESP_LOGD(TAG, " Target Temperature: %.2f°C", this->target_temperature);
426  }
427  if (traits.get_supports_current_humidity()) {
428  ESP_LOGD(TAG, " Current Humidity: %.0f%%", this->current_humidity);
429  }
430  if (traits.get_supports_target_humidity()) {
431  ESP_LOGD(TAG, " Target Humidity: %.0f%%", this->target_humidity);
432  }
433 
434  // Send state to frontend
435  this->state_callback_.call(*this);
436  // Save state
437  this->save_state_();
438 }
439 
441  auto traits = this->traits();
442  if (this->visual_min_temperature_override_.has_value()) {
443  traits.set_visual_min_temperature(*this->visual_min_temperature_override_);
444  }
445  if (this->visual_max_temperature_override_.has_value()) {
446  traits.set_visual_max_temperature(*this->visual_max_temperature_override_);
447  }
448  if (this->visual_target_temperature_step_override_.has_value()) {
449  traits.set_visual_target_temperature_step(*this->visual_target_temperature_step_override_);
450  traits.set_visual_current_temperature_step(*this->visual_current_temperature_step_override_);
451  }
452  if (this->visual_min_humidity_override_.has_value()) {
453  traits.set_visual_min_humidity(*this->visual_min_humidity_override_);
454  }
455  if (this->visual_max_humidity_override_.has_value()) {
456  traits.set_visual_max_humidity(*this->visual_max_humidity_override_);
457  }
458 
459  return traits;
460 }
461 
462 void Climate::set_visual_min_temperature_override(float visual_min_temperature_override) {
463  this->visual_min_temperature_override_ = visual_min_temperature_override;
464 }
465 void Climate::set_visual_max_temperature_override(float visual_max_temperature_override) {
466  this->visual_max_temperature_override_ = visual_max_temperature_override;
467 }
468 void Climate::set_visual_temperature_step_override(float target, float current) {
469  this->visual_target_temperature_step_override_ = target;
470  this->visual_current_temperature_step_override_ = current;
471 }
472 void Climate::set_visual_min_humidity_override(float visual_min_humidity_override) {
473  this->visual_min_humidity_override_ = visual_min_humidity_override;
474 }
475 void Climate::set_visual_max_humidity_override(float visual_max_humidity_override) {
476  this->visual_max_humidity_override_ = visual_max_humidity_override;
477 }
478 
480 
482  auto call = climate->make_call();
483  auto traits = climate->get_traits();
484  call.set_mode(this->mode);
485  if (traits.get_supports_two_point_target_temperature()) {
486  call.set_target_temperature_low(this->target_temperature_low);
487  call.set_target_temperature_high(this->target_temperature_high);
488  } else {
489  call.set_target_temperature(this->target_temperature);
490  }
491  if (traits.get_supports_target_humidity()) {
492  call.set_target_humidity(this->target_humidity);
493  }
494  if (traits.get_supports_fan_modes() || !traits.get_supported_custom_fan_modes().empty()) {
495  call.set_fan_mode(this->fan_mode);
496  }
497  if (traits.get_supports_presets() || !traits.get_supported_custom_presets().empty()) {
498  call.set_preset(this->preset);
499  }
500  if (traits.get_supports_swing_modes()) {
501  call.set_swing_mode(this->swing_mode);
502  }
503  return call;
504 }
506  auto traits = climate->get_traits();
507  climate->mode = this->mode;
508  if (traits.get_supports_two_point_target_temperature()) {
511  } else {
512  climate->target_temperature = this->target_temperature;
513  }
514  if (traits.get_supports_target_humidity()) {
515  climate->target_humidity = this->target_humidity;
516  }
517  if (traits.get_supports_fan_modes() && !this->uses_custom_fan_mode) {
518  climate->fan_mode = this->fan_mode;
519  }
520  if (!traits.get_supported_custom_fan_modes().empty() && this->uses_custom_fan_mode) {
521  // std::set has consistent order (lexicographic for strings), so this is ok
522  const auto &modes = traits.get_supported_custom_fan_modes();
523  std::vector<std::string> modes_vec{modes.begin(), modes.end()};
524  if (custom_fan_mode < modes_vec.size()) {
525  climate->custom_fan_mode = modes_vec[this->custom_fan_mode];
526  }
527  }
528  if (traits.get_supports_presets() && !this->uses_custom_preset) {
529  climate->preset = this->preset;
530  }
531  if (!traits.get_supported_custom_presets().empty() && uses_custom_preset) {
532  // std::set has consistent order (lexicographic for strings), so this is ok
533  const auto &presets = traits.get_supported_custom_presets();
534  std::vector<std::string> presets_vec{presets.begin(), presets.end()};
535  if (custom_preset < presets_vec.size()) {
536  climate->custom_preset = presets_vec[this->custom_preset];
537  }
538  }
539  if (traits.get_supports_swing_modes()) {
540  climate->swing_mode = this->swing_mode;
541  }
542  climate->publish_state();
543 }
544 
545 template<typename T1, typename T2> bool set_alternative(optional<T1> &dst, optional<T2> &alt, const T1 &src) {
546  bool is_changed = alt.has_value();
547  alt.reset();
548  if (is_changed || dst != src) {
549  dst = src;
550  is_changed = true;
551  }
552  return is_changed;
553 }
554 
556  return set_alternative(this->fan_mode, this->custom_fan_mode, mode);
557 }
558 
559 bool Climate::set_custom_fan_mode_(const std::string &mode) {
560  return set_alternative(this->custom_fan_mode, this->fan_mode, mode);
561 }
562 
563 bool Climate::set_preset_(ClimatePreset preset) { return set_alternative(this->preset, this->custom_preset, preset); }
564 
565 bool Climate::set_custom_preset_(const std::string &preset) {
566  return set_alternative(this->custom_preset, this->preset, preset);
567 }
568 
569 void Climate::dump_traits_(const char *tag) {
570  auto traits = this->get_traits();
571  ESP_LOGCONFIG(tag, "ClimateTraits:");
572  ESP_LOGCONFIG(tag, " [x] Visual settings:");
573  ESP_LOGCONFIG(tag, " - Min temperature: %.1f", traits.get_visual_min_temperature());
574  ESP_LOGCONFIG(tag, " - Max temperature: %.1f", traits.get_visual_max_temperature());
575  ESP_LOGCONFIG(tag, " - Temperature step:");
576  ESP_LOGCONFIG(tag, " Target: %.1f", traits.get_visual_target_temperature_step());
577  if (traits.get_supports_current_temperature()) {
578  ESP_LOGCONFIG(tag, " Current: %.1f", traits.get_visual_current_temperature_step());
579  }
580  if (traits.get_supports_target_humidity() || traits.get_supports_current_humidity()) {
581  ESP_LOGCONFIG(tag, " - Min humidity: %.0f", traits.get_visual_min_humidity());
582  ESP_LOGCONFIG(tag, " - Max humidity: %.0f", traits.get_visual_max_humidity());
583  }
584  if (traits.get_supports_two_point_target_temperature()) {
585  ESP_LOGCONFIG(tag, " [x] Supports two-point target temperature");
586  }
587  if (traits.get_supports_current_temperature()) {
588  ESP_LOGCONFIG(tag, " [x] Supports current temperature");
589  }
590  if (traits.get_supports_target_humidity()) {
591  ESP_LOGCONFIG(tag, " [x] Supports target humidity");
592  }
593  if (traits.get_supports_current_humidity()) {
594  ESP_LOGCONFIG(tag, " [x] Supports current humidity");
595  }
596  if (traits.get_supports_action()) {
597  ESP_LOGCONFIG(tag, " [x] Supports action");
598  }
599  if (!traits.get_supported_modes().empty()) {
600  ESP_LOGCONFIG(tag, " [x] Supported modes:");
601  for (ClimateMode m : traits.get_supported_modes())
602  ESP_LOGCONFIG(tag, " - %s", LOG_STR_ARG(climate_mode_to_string(m)));
603  }
604  if (!traits.get_supported_fan_modes().empty()) {
605  ESP_LOGCONFIG(tag, " [x] Supported fan modes:");
606  for (ClimateFanMode m : traits.get_supported_fan_modes())
607  ESP_LOGCONFIG(tag, " - %s", LOG_STR_ARG(climate_fan_mode_to_string(m)));
608  }
609  if (!traits.get_supported_custom_fan_modes().empty()) {
610  ESP_LOGCONFIG(tag, " [x] Supported custom fan modes:");
611  for (const std::string &s : traits.get_supported_custom_fan_modes())
612  ESP_LOGCONFIG(tag, " - %s", s.c_str());
613  }
614  if (!traits.get_supported_presets().empty()) {
615  ESP_LOGCONFIG(tag, " [x] Supported presets:");
616  for (ClimatePreset p : traits.get_supported_presets())
617  ESP_LOGCONFIG(tag, " - %s", LOG_STR_ARG(climate_preset_to_string(p)));
618  }
619  if (!traits.get_supported_custom_presets().empty()) {
620  ESP_LOGCONFIG(tag, " [x] Supported custom presets:");
621  for (const std::string &s : traits.get_supported_custom_presets())
622  ESP_LOGCONFIG(tag, " - %s", s.c_str());
623  }
624  if (!traits.get_supported_swing_modes().empty()) {
625  ESP_LOGCONFIG(tag, " [x] Supported swing modes:");
626  for (ClimateSwingMode m : traits.get_supported_swing_modes())
627  ESP_LOGCONFIG(tag, " - %s", LOG_STR_ARG(climate_swing_mode_to_string(m)));
628  }
629 }
630 
631 } // namespace climate
632 } // namespace esphome
This class is used to encode all control actions on a climate device.
Definition: climate.h:33
The fan mode is set to Low.
Definition: climate_mode.h:54
value_type const & value() const
Definition: optional.h:89
The fan mode is set to Quiet.
Definition: climate_mode.h:66
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition: climate.h:202
float target_temperature_low
Definition: climate.h:140
optional< std::string > custom_preset_
Definition: climate.h:120
The fan mode is set to Both.
Definition: climate_mode.h:74
ClimatePreset
Enum for all preset modes.
Definition: climate_mode.h:82
float target_temperature
The target temperature of the climate device.
Definition: climate.h:186
Device is in home preset.
Definition: climate_mode.h:86
const optional< ClimateMode > & get_mode() const
Definition: climate.cpp:273
optional< float > target_temperature_
Definition: climate.h:112
The fan mode is set to Middle.
Definition: climate_mode.h:60
This class contains all static data for climate devices.
void set_visual_min_humidity_override(float visual_min_humidity_override)
Definition: climate.cpp:472
const LogString * climate_mode_to_string(ClimateMode mode)
Convert the given ClimateMode to a human-readable string.
Definition: climate_mode.cpp:6
The climate device is set to heat to reach the target temperature.
Definition: climate_mode.h:18
CallbackManager< void(ClimateCall &)> control_callback_
Definition: climate.h:296
Struct used to save the state of the climate device in restore memory.
Definition: climate.h:125
ClimateMode mode
The active mode of the climate device.
Definition: climate.h:173
bool set_alternative(optional< T1 > &dst, optional< T2 > &alt, const T1 &src)
Definition: climate.cpp:545
optional< ClimateFanMode > fan_mode_
Definition: climate.h:116
const optional< float > & get_target_temperature_low() const
Definition: climate.cpp:275
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:322
float target_temperature_high
The maximum target temperature of the climate device, for climate devices with split target temperatu...
Definition: climate.h:191
The fan mode is set to Diffuse.
Definition: climate_mode.h:64
optional< float > target_temperature_high_
Definition: climate.h:114
bool has_value() const
Definition: optional.h:87
The climate device is set to dry/humidity mode.
Definition: climate_mode.h:22
float target_temperature_high
Definition: climate.h:141
bool uses_custom_fan_mode
Definition: climate.h:571
float target_humidity
The target humidity of the climate device.
Definition: climate.h:196
ClimateCall & set_swing_mode(ClimateSwingMode swing_mode)
Set the swing mode of the climate device.
Definition: climate.cpp:237
float target_humidity
Definition: climate.h:589
void set_visual_max_humidity_override(float visual_max_humidity_override)
Definition: climate.cpp:475
ClimateSwingMode swing_mode
Definition: climate.h:581
ClimateSwingMode
Enum for all modes a climate swing can be in.
Definition: climate_mode.h:70
bool supports_custom_preset(const std::string &custom_preset) const
Device is prepared for sleep.
Definition: climate_mode.h:96
optional< std::string > custom_fan_mode
The active custom fan mode of the climate device.
Definition: climate.h:205
Device is in away preset.
Definition: climate_mode.h:88
bool supports_custom_fan_mode(const std::string &custom_fan_mode) const
void apply(Climate *climate)
Apply these settings to the climate device.
Definition: climate.cpp:505
ClimateCall & set_target_temperature_low(float target_temperature_low)
Set the low point target temperature of the climate device.
Definition: climate.cpp:260
ClimateCall make_call()
Make a climate device control call, this is used to control the climate device, see the ClimateCall d...
Definition: climate.cpp:479
Device is in comfort preset.
Definition: climate_mode.h:92
const optional< std::string > & get_custom_preset() const
Definition: climate.cpp:281
ClimateCall & set_target_temperature(float target_temperature)
Set the target temperature of the climate device.
Definition: climate.cpp:256
The fan mode is set to Horizontal.
Definition: climate_mode.h:78
The climate device is set to cool to reach the target temperature.
Definition: climate_mode.h:16
optional< ClimateSwingMode > swing_mode_
Definition: climate.h:117
Device is reacting to activity (e.g., movement sensors)
Definition: climate_mode.h:98
const optional< ClimatePreset > & get_preset() const
Definition: climate.cpp:280
The fan mode is set to Auto.
Definition: climate_mode.h:52
optional< ClimatePreset > preset
The active preset of the climate device.
Definition: climate.h:208
uint8_t custom_preset
Definition: climate.h:579
ESPPreferences * global_preferences
optional< ClimatePreset > preset_
Definition: climate.h:119
ClimateCall & set_preset(ClimatePreset preset)
Set the preset of the climate device.
Definition: climate.cpp:199
BedjetMode mode
BedJet operating mode.
Definition: bedjet_codec.h:183
virtual void control(const ClimateCall &call)=0
Control the climate device, this is a virtual method that each climate integration must implement...
ClimateCall & set_fan_mode(ClimateFanMode fan_mode)
Set the fan mode of the climate device.
Definition: climate.cpp:157
ClimateTraits get_traits()
Get the traits of this climate device with all overrides applied.
Definition: climate.cpp:440
const LogString * climate_preset_to_string(ClimatePreset preset)
Convert the given PresetMode to a human-readable string.
The climate device is adjusting the temperatre dynamically.
Definition: climate_mode.h:27
The climate device is set to heat/cool to reach the target temperature.
Definition: climate_mode.h:14
The fan mode is set to Vertical.
Definition: climate_mode.h:76
void set_visual_max_temperature_override(float visual_max_temperature_override)
Definition: climate.cpp:465
The fan mode is set to Focus.
Definition: climate_mode.h:62
const optional< std::string > & get_custom_fan_mode() const
Definition: climate.cpp:279
void set_visual_min_temperature_override(float visual_min_temperature_override)
Definition: climate.cpp:462
The fan mode is set to Off.
Definition: climate_mode.h:50
const optional< float > & get_target_temperature() const
Definition: climate.cpp:274
optional< std::string > custom_fan_mode_
Definition: climate.h:118
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition: climate.cpp:395
bool set_custom_fan_mode_(const std::string &mode)
Set custom fan mode. Reset primary fan mode. Return true if fan mode has been changed.
Definition: climate.cpp:559
The fan mode is set to High.
Definition: climate_mode.h:58
ClimateCall & set_target_humidity(float target_humidity)
Set the target humidity of the climate device.
Definition: climate.cpp:268
ClimateMode
Enum for all modes a climate device can be in.
Definition: climate_mode.h:10
The swing mode is set to Off.
Definition: climate_mode.h:72
The climate device is off.
Definition: climate_mode.h:12
ClimateFanMode fan_mode
Definition: climate.h:573
constexpr const char * c_str() const
Definition: string_ref.h:68
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:318
optional< std::string > custom_preset
The active custom preset mode of the climate device.
Definition: climate.h:211
ClimateCall & set_target_temperature_high(float target_temperature_high)
Set the high point target temperature of the climate device.
Definition: climate.cpp:264
const LogString * climate_fan_mode_to_string(ClimateFanMode fan_mode)
Convert the given ClimateFanMode to a human-readable string.
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition: climate.h:199
void set_visual_temperature_step_override(float target, float current)
Definition: climate.cpp:468
const optional< ClimateFanMode > & get_fan_mode() const
Definition: climate.cpp:278
optional< float > target_humidity_
Definition: climate.h:115
Device is in boost preset.
Definition: climate_mode.h:90
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
ClimateCall & set_mode(ClimateMode mode)
Set the mode of the climate device.
Definition: climate.cpp:133
The fan mode is set to On.
Definition: climate_mode.h:48
bool set_custom_preset_(const std::string &preset)
Set custom preset. Reset primary preset. Return true if preset has been changed.
Definition: climate.cpp:565
bool uses_custom_preset
Definition: climate.h:576
const optional< ClimateSwingMode > & get_swing_mode() const
Definition: climate.cpp:282
void save_state_()
Internal method to save the state of the climate device to recover memory.
Definition: climate.cpp:337
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
optional< ClimateMode > mode_
Definition: climate.h:111
ClimateCall(Climate *parent)
Definition: climate.h:35
void dump_traits_(const char *tag)
Definition: climate.cpp:569
Device is running an energy-saving preset.
Definition: climate_mode.h:94
optional< ClimateDeviceRestoreState > restore_state_()
Restore the state of the climate device, call this from your setup() method.
Definition: climate.cpp:329
The fan mode is set to Medium.
Definition: climate_mode.h:56
const optional< float > & get_target_temperature_high() const
Definition: climate.cpp:276
uint8_t m
Definition: bl0906.h:208
The climate device only has the fan enabled, no heating or cooling is taking place.
Definition: climate_mode.h:20
const LogString * climate_action_to_string(ClimateAction action)
Convert the given ClimateAction to a human-readable string.
bool set_preset_(ClimatePreset preset)
Set preset. Reset custom preset. Return true if preset has been changed.
Definition: climate.cpp:563
uint8_t custom_fan_mode
Definition: climate.h:574
optional< float > target_temperature_low_
Definition: climate.h:113
float target_temperature
Definition: climate.h:138
const optional< float > & get_target_humidity() const
Definition: climate.cpp:277
ClimateCall to_call(Climate *climate)
Convert this struct to a climate call that can be performed.
Definition: climate.cpp:481
float target_temperature_low
The minimum target temperature of the climate device, for climate devices with split target temperatu...
Definition: climate.h:189
const StringRef & get_name() const
Definition: entity_base.cpp:10
bool set_fan_mode_(ClimateFanMode mode)
Set fan mode. Reset custom fan mode. Return true if fan mode has been changed.
Definition: climate.cpp:555
ClimatePreset preset
Definition: climate.h:578
ClimateDevice - This is the base class for all climate integrations.
Definition: climate.h:168
bool state
Definition: fan.h:34
bool str_equals_case_insensitive(const std::string &a, const std::string &b)
Compare strings for equality in case-insensitive manner.
Definition: helpers.cpp:259
Climate *const parent_
Definition: climate.h:110
const LogString * climate_swing_mode_to_string(ClimateSwingMode swing_mode)
Convert the given ClimateSwingMode to a human-readable string.