ESPHome 2025.5.0
Loading...
Searching...
No Matches
thermostat_climate.cpp
Go to the documentation of this file.
2#include "esphome/core/log.h"
3
4namespace esphome {
5namespace thermostat {
6
7static const char *const TAG = "thermostat.climate";
8
10 if (this->use_startup_delay_) {
11 // start timers so that no actions are called for a moment
17 }
18 // add a callback so that whenever the sensor state changes we can take action
19 this->sensor_->add_on_state_callback([this](float state) {
21 // required action may have changed, recompute, refresh, we'll publish_state() later
22 this->switch_to_action_(this->compute_action_(), false);
24 // current temperature and possibly action changed, so publish the new state
25 this->publish_state();
26 });
27 this->current_temperature = this->sensor_->state;
28
29 // register for humidity values and get initial state
30 if (this->humidity_sensor_ != nullptr) {
31 this->humidity_sensor_->add_on_state_callback([this](float state) {
32 this->current_humidity = state;
33 this->publish_state();
34 });
36 }
37
38 auto use_default_preset = true;
39
41 // restore all climate data, if possible
42 auto restore = this->restore_state_();
43 if (restore.has_value()) {
44 use_default_preset = false;
45 restore->to_call(this).perform();
46 }
47 }
48
49 // Either we failed to restore state or the user has requested we always apply the default preset
50 if (use_default_preset) {
53 } else if (!this->default_custom_preset_.empty()) {
55 }
56 }
57
58 // refresh the climate action based on the restored settings, we'll publish_state() later
59 this->switch_to_action_(this->compute_action_(), false);
61 this->setup_complete_ = true;
62 this->publish_state();
63}
64
66 for (auto &timer : this->timer_) {
67 if (timer.active && (timer.started + timer.time < millis())) {
68 timer.active = false;
69 timer.func();
70 }
71 }
72}
73
78
80 this->switch_to_mode_(this->mode, false);
81 this->switch_to_action_(this->compute_action_(), false);
83 this->switch_to_fan_mode_(this->fan_mode.value(), false);
84 this->switch_to_swing_mode_(this->swing_mode, false);
86 this->publish_state();
87}
88
90 bool state_mismatch = this->action != this->compute_action_(true);
91
92 switch (this->compute_action_(true)) {
95 return state_mismatch && (!this->idle_action_ready_());
97 return state_mismatch && (!this->cooling_action_ready_());
99 return state_mismatch && (!this->heating_action_ready_());
101 return state_mismatch && (!this->fanning_action_ready_());
103 return state_mismatch && (!this->drying_action_ready_());
104 default:
105 break;
106 }
107 return false;
108}
109
111 bool state_mismatch = this->fan_mode.value_or(climate::CLIMATE_FAN_ON) != this->prev_fan_mode_;
112 return state_mismatch && (!this->fan_mode_ready_());
113}
114
116
118
120 if ((this->supports_cool_ || (this->supports_fan_only_ && this->supports_fan_only_cooling_)) &&
121 (std::isnan(this->cooling_deadband_) || std::isnan(this->cooling_overrun_)))
122 return false;
123
124 if (this->supports_heat_ && (std::isnan(this->heating_deadband_) || std::isnan(this->heating_overrun_)))
125 return false;
126
127 return true;
128}
129
131 if (std::isnan(this->target_temperature)) {
132 this->target_temperature =
135 } else {
136 // target_temperature must be between the visual minimum and the visual maximum
137 if (this->target_temperature < this->get_traits().get_visual_min_temperature())
139 if (this->target_temperature > this->get_traits().get_visual_max_temperature())
141 }
142}
143
152
154 if (std::isnan(this->target_temperature_low)) {
156 } else {
157 // target_temperature_low must not be lower than the visual minimum
158 if (this->target_temperature_low < this->get_traits().get_visual_min_temperature())
160 // target_temperature_low must not be greater than the visual maximum minus set_point_minimum_differential_
161 if (this->target_temperature_low >
162 this->get_traits().get_visual_max_temperature() - this->set_point_minimum_differential_) {
165 }
166 // if target_temperature_low is set greater than target_temperature_high, move up target_temperature_high
169 }
170}
171
173 if (std::isnan(this->target_temperature_high)) {
175 } else {
176 // target_temperature_high must not be lower than the visual maximum
177 if (this->target_temperature_high > this->get_traits().get_visual_max_temperature())
179 // target_temperature_high must not be lower than the visual minimum plus set_point_minimum_differential_
180 if (this->target_temperature_high <
181 this->get_traits().get_visual_min_temperature() + this->set_point_minimum_differential_) {
184 }
185 // if target_temperature_high is set less than target_temperature_low, move down target_temperature_low
188 }
189}
190
192 if (call.get_preset().has_value()) {
193 // setup_complete_ blocks modifying/resetting the temps immediately after boot
194 if (this->setup_complete_) {
195 this->change_preset_(*call.get_preset());
196 } else {
197 this->preset = *call.get_preset();
198 }
199 }
200 if (call.get_custom_preset().has_value()) {
201 // setup_complete_ blocks modifying/resetting the temps immediately after boot
202 if (this->setup_complete_) {
204 } else {
205 this->custom_preset = *call.get_custom_preset();
206 }
207 }
208
209 if (call.get_mode().has_value())
210 this->mode = *call.get_mode();
211 if (call.get_fan_mode().has_value())
212 this->fan_mode = *call.get_fan_mode();
213 if (call.get_swing_mode().has_value())
214 this->swing_mode = *call.get_swing_mode();
215 if (this->supports_two_points_) {
219 }
220 if (call.get_target_temperature_high().has_value()) {
223 }
224 } else {
225 if (call.get_target_temperature().has_value()) {
228 }
229 }
230 // make any changes happen
231 refresh();
232}
233
237 if (this->humidity_sensor_ != nullptr)
239
240 if (supports_auto_)
244 if (supports_cool_)
246 if (supports_dry_)
250 if (supports_heat_)
252
273
282
283 for (auto &it : this->preset_config_) {
285 }
286 for (auto &it : this->custom_preset_config_) {
288 }
289
292 return traits;
293}
294
296 auto target_action = climate::CLIMATE_ACTION_IDLE;
297 // if any hysteresis values or current_temperature is not valid, we go to OFF;
298 if (std::isnan(this->current_temperature) || !this->hysteresis_valid()) {
300 }
301 // do not change the action if an "ON" timer is running
302 if ((!ignore_timers) &&
305 return this->action;
306 }
307
308 // ensure set point(s) is/are valid before computing the action
310 // everything has been validated so we can now safely compute the action
311 switch (this->mode) {
312 // if the climate mode is OFF then the climate action must be OFF
314 target_action = climate::CLIMATE_ACTION_OFF;
315 break;
317 if (this->fanning_required_())
318 target_action = climate::CLIMATE_ACTION_FAN;
319 break;
321 target_action = climate::CLIMATE_ACTION_DRYING;
322 break;
324 if (this->cooling_required_() && this->heating_required_()) {
325 // this is bad and should never happen, so just stop.
326 // target_action = climate::CLIMATE_ACTION_IDLE;
327 } else if (this->cooling_required_()) {
328 target_action = climate::CLIMATE_ACTION_COOLING;
329 } else if (this->heating_required_()) {
330 target_action = climate::CLIMATE_ACTION_HEATING;
331 }
332 break;
334 if (this->cooling_required_()) {
335 target_action = climate::CLIMATE_ACTION_COOLING;
336 }
337 break;
339 if (this->heating_required_()) {
340 target_action = climate::CLIMATE_ACTION_HEATING;
341 }
342 break;
343 default:
344 break;
345 }
346 // do not abruptly switch actions. cycle through IDLE, first. we'll catch this at the next update.
348 (target_action == climate::CLIMATE_ACTION_HEATING)) ||
350 ((target_action == climate::CLIMATE_ACTION_COOLING) || (target_action == climate::CLIMATE_ACTION_DRYING)))) {
352 }
353
354 return target_action;
355}
356
358 auto target_action = climate::CLIMATE_ACTION_IDLE;
359 // if any hysteresis values or current_temperature is not valid, we go to OFF;
360 if (std::isnan(this->current_temperature) || !this->hysteresis_valid()) {
362 }
363
364 // ensure set point(s) is/are valid before computing the action
366 // everything has been validated so we can now safely compute the action
367 switch (this->mode) {
368 // if the climate mode is OFF then the climate action must be OFF
370 target_action = climate::CLIMATE_ACTION_OFF;
371 break;
374 // this is bad and should never happen, so just stop.
375 // target_action = climate::CLIMATE_ACTION_IDLE;
376 } else if (this->supplemental_cooling_required_()) {
377 target_action = climate::CLIMATE_ACTION_COOLING;
378 } else if (this->supplemental_heating_required_()) {
379 target_action = climate::CLIMATE_ACTION_HEATING;
380 }
381 break;
383 if (this->supplemental_cooling_required_()) {
384 target_action = climate::CLIMATE_ACTION_COOLING;
385 }
386 break;
388 if (this->supplemental_heating_required_()) {
389 target_action = climate::CLIMATE_ACTION_HEATING;
390 }
391 break;
392 default:
393 break;
394 }
395
396 return target_action;
397}
398
400 // setup_complete_ helps us ensure an action is called immediately after boot
401 if ((action == this->action) && this->setup_complete_) {
402 // already in target mode
403 return;
404 }
405
406 if (((action == climate::CLIMATE_ACTION_OFF && this->action == climate::CLIMATE_ACTION_IDLE) ||
408 this->setup_complete_) {
409 // switching from OFF to IDLE or vice-versa -- this is only a visual difference.
410 // OFF means user manually disabled, IDLE means the temperature is in target range.
411 this->action = action;
412 if (publish_state)
413 this->publish_state();
414 return;
415 }
416
417 bool action_ready = false;
418 Trigger<> *trig = this->idle_action_trigger_, *trig_fan = nullptr;
419 switch (action) {
422 if (this->idle_action_ready_()) {
424 if (this->action == climate::CLIMATE_ACTION_COOLING)
426 if (this->action == climate::CLIMATE_ACTION_FAN) {
429 } else {
431 }
432 }
433 if (this->action == climate::CLIMATE_ACTION_HEATING)
435 // trig = this->idle_action_trigger_;
436 ESP_LOGVV(TAG, "Switching to IDLE/OFF action");
437 this->cooling_max_runtime_exceeded_ = false;
438 this->heating_max_runtime_exceeded_ = false;
439 action_ready = true;
440 }
441 break;
443 if (this->cooling_action_ready_()) {
446 if (this->supports_fan_with_cooling_) {
448 trig_fan = this->fan_only_action_trigger_;
449 }
450 this->cooling_max_runtime_exceeded_ = false;
451 trig = this->cool_action_trigger_;
452 ESP_LOGVV(TAG, "Switching to COOLING action");
453 action_ready = true;
454 }
455 break;
457 if (this->heating_action_ready_()) {
460 if (this->supports_fan_with_heating_) {
462 trig_fan = this->fan_only_action_trigger_;
463 }
464 this->heating_max_runtime_exceeded_ = false;
465 trig = this->heat_action_trigger_;
466 ESP_LOGVV(TAG, "Switching to HEATING action");
467 action_ready = true;
468 }
469 break;
471 if (this->fanning_action_ready_()) {
474 } else {
476 }
477 trig = this->fan_only_action_trigger_;
478 ESP_LOGVV(TAG, "Switching to FAN_ONLY action");
479 action_ready = true;
480 }
481 break;
483 if (this->drying_action_ready_()) {
486 trig = this->dry_action_trigger_;
487 ESP_LOGVV(TAG, "Switching to DRYING action");
488 action_ready = true;
489 }
490 break;
491 default:
492 // we cannot report an invalid mode back to HA (even if it asked for one)
493 // and must assume some valid value
495 // trig = this->idle_action_trigger_;
496 }
497
498 if (action_ready) {
499 if (this->prev_action_trigger_ != nullptr) {
501 this->prev_action_trigger_ = nullptr;
502 }
503 this->action = action;
504 this->prev_action_trigger_ = trig;
505 if (trig != nullptr) {
506 trig->trigger();
507 }
508 // if enabled, call the fan_only action with cooling/heating actions
509 if (trig_fan != nullptr) {
510 ESP_LOGVV(TAG, "Calling FAN_ONLY action with HEATING/COOLING action");
511 trig_fan->trigger();
512 }
513 if (publish_state)
514 this->publish_state();
515 }
516}
517
519 // setup_complete_ helps us ensure an action is called immediately after boot
520 if ((action == this->supplemental_action_) && this->setup_complete_) {
521 // already in target mode
522 return;
523 }
524
525 switch (action) {
530 break;
533 break;
536 break;
537 default:
538 return;
539 }
540 ESP_LOGVV(TAG, "Updating supplemental action...");
543}
544
546 Trigger<> *trig = nullptr;
547
548 switch (this->supplemental_action_) {
552 }
554 ESP_LOGVV(TAG, "Calling supplemental COOLING action");
555 break;
559 }
561 ESP_LOGVV(TAG, "Calling supplemental HEATING action");
562 break;
563 default:
564 break;
565 }
566
567 if (trig != nullptr) {
568 trig->trigger();
569 }
570}
571
573 // setup_complete_ helps us ensure an action is called immediately after boot
574 if ((fan_mode == this->prev_fan_mode_) && this->setup_complete_) {
575 // already in target mode
576 return;
577 }
578
579 this->fan_mode = fan_mode;
580 if (publish_state)
581 this->publish_state();
582
583 if (this->fan_mode_ready_()) {
584 Trigger<> *trig = this->fan_mode_auto_trigger_;
585 switch (fan_mode) {
587 trig = this->fan_mode_on_trigger_;
588 ESP_LOGVV(TAG, "Switching to FAN_ON mode");
589 break;
591 trig = this->fan_mode_off_trigger_;
592 ESP_LOGVV(TAG, "Switching to FAN_OFF mode");
593 break;
595 // trig = this->fan_mode_auto_trigger_;
596 ESP_LOGVV(TAG, "Switching to FAN_AUTO mode");
597 break;
599 trig = this->fan_mode_low_trigger_;
600 ESP_LOGVV(TAG, "Switching to FAN_LOW mode");
601 break;
603 trig = this->fan_mode_medium_trigger_;
604 ESP_LOGVV(TAG, "Switching to FAN_MEDIUM mode");
605 break;
607 trig = this->fan_mode_high_trigger_;
608 ESP_LOGVV(TAG, "Switching to FAN_HIGH mode");
609 break;
611 trig = this->fan_mode_middle_trigger_;
612 ESP_LOGVV(TAG, "Switching to FAN_MIDDLE mode");
613 break;
615 trig = this->fan_mode_focus_trigger_;
616 ESP_LOGVV(TAG, "Switching to FAN_FOCUS mode");
617 break;
619 trig = this->fan_mode_diffuse_trigger_;
620 ESP_LOGVV(TAG, "Switching to FAN_DIFFUSE mode");
621 break;
623 trig = this->fan_mode_quiet_trigger_;
624 ESP_LOGVV(TAG, "Switching to FAN_QUIET mode");
625 break;
626 default:
627 // we cannot report an invalid mode back to HA (even if it asked for one)
628 // and must assume some valid value
630 // trig = this->fan_mode_auto_trigger_;
631 }
632 if (this->prev_fan_mode_trigger_ != nullptr) {
634 this->prev_fan_mode_trigger_ = nullptr;
635 }
637 if (trig != nullptr) {
638 trig->trigger();
639 }
640 this->prev_fan_mode_ = fan_mode;
641 this->prev_fan_mode_trigger_ = trig;
642 }
643}
644
646 // setup_complete_ helps us ensure an action is called immediately after boot
647 if ((mode == this->prev_mode_) && this->setup_complete_) {
648 // already in target mode
649 return;
650 }
651
652 if (this->prev_mode_trigger_ != nullptr) {
654 this->prev_mode_trigger_ = nullptr;
655 }
656 Trigger<> *trig = this->auto_mode_trigger_;
657 switch (mode) {
659 trig = this->off_mode_trigger_;
660 break;
662 // trig = this->auto_mode_trigger_;
663 break;
665 trig = this->cool_mode_trigger_;
666 break;
668 trig = this->heat_mode_trigger_;
669 break;
671 trig = this->fan_only_mode_trigger_;
672 break;
674 trig = this->dry_mode_trigger_;
675 break;
676 default:
677 // we cannot report an invalid mode back to HA (even if it asked for one)
678 // and must assume some valid value
680 // trig = this->auto_mode_trigger_;
681 }
682 if (trig != nullptr) {
683 trig->trigger();
684 }
685 this->mode = mode;
686 this->prev_mode_ = mode;
687 this->prev_mode_trigger_ = trig;
688 if (publish_state)
689 this->publish_state();
690}
691
693 // setup_complete_ helps us ensure an action is called immediately after boot
694 if ((swing_mode == this->prev_swing_mode_) && this->setup_complete_) {
695 // already in target mode
696 return;
697 }
698
699 if (this->prev_swing_mode_trigger_ != nullptr) {
701 this->prev_swing_mode_trigger_ = nullptr;
702 }
704 switch (swing_mode) {
706 trig = this->swing_mode_both_trigger_;
707 break;
710 break;
712 // trig = this->swing_mode_off_trigger_;
713 break;
715 trig = this->swing_mode_vertical_trigger_;
716 break;
717 default:
718 // we cannot report an invalid mode back to HA (even if it asked for one)
719 // and must assume some valid value
720 swing_mode = climate::CLIMATE_SWING_OFF;
721 // trig = this->swing_mode_off_trigger_;
722 }
723 if (trig != nullptr) {
724 trig->trigger();
725 }
726 this->swing_mode = swing_mode;
728 this->prev_swing_mode_trigger_ = trig;
729 if (publish_state)
730 this->publish_state();
731}
732
741
746
751
753
760
765
767 if (this->timer_duration_(timer_index) > 0) {
768 this->timer_[timer_index].started = millis();
769 this->timer_[timer_index].active = true;
770 }
771}
772
774 auto ret = this->timer_[timer_index].active;
775 this->timer_[timer_index].active = false;
776 return ret;
777}
778
780 return this->timer_[timer_index].active;
781}
782
784 return this->timer_[timer_index].time;
785}
786
788 return this->timer_[timer_index].func;
789}
790
792 ESP_LOGVV(TAG, "cooling_max_run_time timer expired");
796}
797
799 ESP_LOGVV(TAG, "cooling_off timer expired");
800 this->switch_to_action_(this->compute_action_());
802}
803
805 ESP_LOGVV(TAG, "cooling_on timer expired");
806 this->switch_to_action_(this->compute_action_());
808}
809
811 ESP_LOGVV(TAG, "fan_mode timer expired");
814 this->switch_to_action_(this->compute_action_());
815}
816
818 ESP_LOGVV(TAG, "fanning_off timer expired");
819 this->switch_to_action_(this->compute_action_());
820}
821
823 ESP_LOGVV(TAG, "fanning_on timer expired");
824 this->switch_to_action_(this->compute_action_());
825}
826
828 ESP_LOGVV(TAG, "heating_max_run_time timer expired");
832}
833
835 ESP_LOGVV(TAG, "heating_off timer expired");
836 this->switch_to_action_(this->compute_action_());
838}
839
841 ESP_LOGVV(TAG, "heating_on timer expired");
842 this->switch_to_action_(this->compute_action_());
844}
845
847 ESP_LOGVV(TAG, "idle_on timer expired");
848 this->switch_to_action_(this->compute_action_());
850}
851
853 if (this->supports_two_points_) {
854 // setup_complete_ helps us ensure an action is called immediately after boot
857 return; // nothing changed, no reason to trigger
858 } else {
859 // save the new temperatures so we can check them again later; the trigger will fire below
862 }
863 } else {
864 if ((this->prev_target_temperature_ == this->target_temperature) && this->setup_complete_) {
865 return; // nothing changed, no reason to trigger
866 } else {
867 // save the new temperature so we can check it again later; the trigger will fire below
869 }
870 }
871 // trigger the action
873 if (trig != nullptr) {
874 trig->trigger();
875 }
876}
877
880
881 if (this->supports_cool_) {
883 // if the current temperature exceeds the target + deadband, cooling is required
884 return true;
886 // if the current temperature is less than the target - overrun, cooling should stop
887 return false;
888 } else {
889 // if we get here, the current temperature is between target + deadband and target - overrun,
890 // so the action should not change unless it conflicts with the current mode
891 return (this->action == climate::CLIMATE_ACTION_COOLING) &&
893 }
894 }
895 return false;
896}
897
900
901 if (this->supports_fan_only_) {
902 if (this->supports_fan_only_cooling_) {
904 // if the current temperature exceeds the target + deadband, fanning is required
905 return true;
907 // if the current temperature is less than the target - overrun, fanning should stop
908 return false;
909 } else {
910 // if we get here, the current temperature is between target + deadband and target - overrun,
911 // so the action should not change unless it conflicts with the current mode
913 }
914 } else {
915 return true;
916 }
917 }
918 return false;
919}
920
923
924 if (this->supports_heat_) {
926 // if the current temperature is below the target - deadband, heating is required
927 return true;
928 } else if (this->current_temperature > temperature + this->heating_overrun_) {
929 // if the current temperature is above the target + overrun, heating should stop
930 return false;
931 } else {
932 // if we get here, the current temperature is between target - deadband and target + overrun,
933 // so the action should not change unless it conflicts with the current mode
934 return (this->action == climate::CLIMATE_ACTION_HEATING) &&
936 }
937 }
938 return false;
939}
940
943 // the component must supports_cool_ and the climate action must be climate::CLIMATE_ACTION_COOLING. then...
944 // supplemental cooling is required if the max delta or max runtime was exceeded or the action is already engaged
945 return this->supports_cool_ && (this->action == climate::CLIMATE_ACTION_COOLING) &&
949}
950
953 // the component must supports_heat_ and the climate action must be climate::CLIMATE_ACTION_HEATING. then...
954 // supplemental heating is required if the max delta or max runtime was exceeded or the action is already engaged
955 return this->supports_heat_ && (this->action == climate::CLIMATE_ACTION_HEATING) &&
959}
960
962 bool is_default_preset) {
963 ESP_LOGCONFIG(TAG, " %s Is Default: %s", preset_name, YESNO(is_default_preset));
964
965 if (this->supports_heat_) {
966 if (this->supports_two_points_) {
967 ESP_LOGCONFIG(TAG, " %s Default Target Temperature Low: %.1f°C", preset_name,
969 } else {
970 ESP_LOGCONFIG(TAG, " %s Default Target Temperature Low: %.1f°C", preset_name, config.default_temperature);
971 }
972 }
973 if ((this->supports_cool_) || (this->supports_fan_only_)) {
974 if (this->supports_two_points_) {
975 ESP_LOGCONFIG(TAG, " %s Default Target Temperature High: %.1f°C", preset_name,
977 } else {
978 ESP_LOGCONFIG(TAG, " %s Default Target Temperature High: %.1f°C", preset_name, config.default_temperature);
979 }
980 }
981
982 if (config.mode_.has_value()) {
983 ESP_LOGCONFIG(TAG, " %s Default Mode: %s", preset_name,
984 LOG_STR_ARG(climate::climate_mode_to_string(*config.mode_)));
985 }
986 if (config.fan_mode_.has_value()) {
987 ESP_LOGCONFIG(TAG, " %s Default Fan Mode: %s", preset_name,
988 LOG_STR_ARG(climate::climate_fan_mode_to_string(*config.fan_mode_)));
989 }
990 if (config.swing_mode_.has_value()) {
991 ESP_LOGCONFIG(TAG, " %s Default Swing Mode: %s", preset_name,
993 }
994}
995
997 auto config = this->preset_config_.find(preset);
998
999 if (config != this->preset_config_.end()) {
1000 ESP_LOGI(TAG, "Preset %s requested", LOG_STR_ARG(climate::climate_preset_to_string(preset)));
1001 if (this->change_preset_internal_(config->second) || (!this->preset.has_value()) ||
1002 this->preset.value() != preset) {
1003 // Fire any preset changed trigger if defined
1004 Trigger<> *trig = this->preset_change_trigger_;
1005 this->preset = preset;
1006 if (trig != nullptr) {
1007 trig->trigger();
1008 }
1009
1010 this->refresh();
1011 ESP_LOGI(TAG, "Preset %s applied", LOG_STR_ARG(climate::climate_preset_to_string(preset)));
1012 } else {
1013 ESP_LOGI(TAG, "No changes required to apply preset %s", LOG_STR_ARG(climate::climate_preset_to_string(preset)));
1014 }
1015 this->custom_preset.reset();
1016 this->preset = preset;
1017 } else {
1018 ESP_LOGE(TAG, "Preset %s is not configured, ignoring.", LOG_STR_ARG(climate::climate_preset_to_string(preset)));
1019 }
1020}
1021
1023 auto config = this->custom_preset_config_.find(custom_preset);
1024
1025 if (config != this->custom_preset_config_.end()) {
1026 ESP_LOGI(TAG, "Custom preset %s requested", custom_preset.c_str());
1027 if (this->change_preset_internal_(config->second) || (!this->custom_preset.has_value()) ||
1028 this->custom_preset.value() != custom_preset) {
1029 // Fire any preset changed trigger if defined
1030 Trigger<> *trig = this->preset_change_trigger_;
1031 this->custom_preset = custom_preset;
1032 if (trig != nullptr) {
1033 trig->trigger();
1034 }
1035
1036 this->refresh();
1037 ESP_LOGI(TAG, "Custom preset %s applied", custom_preset.c_str());
1038 } else {
1039 ESP_LOGI(TAG, "No changes required to apply custom preset %s", custom_preset.c_str());
1040 }
1041 this->preset.reset();
1042 this->custom_preset = custom_preset;
1043 } else {
1044 ESP_LOGE(TAG, "Custom Preset %s is not configured, ignoring.", custom_preset.c_str());
1045 }
1046}
1047
1049 bool something_changed = false;
1050
1051 if (this->supports_two_points_) {
1052 if (this->target_temperature_low != config.default_temperature_low) {
1054 something_changed = true;
1055 }
1058 something_changed = true;
1059 }
1060 } else {
1061 if (this->target_temperature != config.default_temperature) {
1063 something_changed = true;
1064 }
1065 }
1066
1067 // Note: The mode, fan_mode and swing_mode can all be defined in the preset but if the climate.control call
1068 // also specifies them then the climate.control call's values will override the preset's values for that call
1069 if (config.mode_.has_value() && (this->mode != config.mode_.value())) {
1070 ESP_LOGV(TAG, "Setting mode to %s", LOG_STR_ARG(climate::climate_mode_to_string(*config.mode_)));
1071 this->mode = *config.mode_;
1072 something_changed = true;
1073 }
1074
1075 if (config.fan_mode_.has_value() && (this->fan_mode != config.fan_mode_.value())) {
1076 ESP_LOGV(TAG, "Setting fan mode to %s", LOG_STR_ARG(climate::climate_fan_mode_to_string(*config.fan_mode_)));
1077 this->fan_mode = *config.fan_mode_;
1078 something_changed = true;
1079 }
1080
1081 if (config.swing_mode_.has_value() && (this->swing_mode != config.swing_mode_.value())) {
1082 ESP_LOGV(TAG, "Setting swing mode to %s", LOG_STR_ARG(climate::climate_swing_mode_to_string(*config.swing_mode_)));
1083 this->swing_mode = *config.swing_mode_;
1084 something_changed = true;
1085 }
1086
1087 return something_changed;
1088}
1089
1094
1096 const ThermostatClimateTargetTempConfig &config) {
1097 this->custom_preset_config_[name] = config;
1098}
1099
1101 : cool_action_trigger_(new Trigger<>()),
1102 supplemental_cool_action_trigger_(new Trigger<>()),
1103 cool_mode_trigger_(new Trigger<>()),
1104 dry_action_trigger_(new Trigger<>()),
1105 dry_mode_trigger_(new Trigger<>()),
1106 heat_action_trigger_(new Trigger<>()),
1107 supplemental_heat_action_trigger_(new Trigger<>()),
1108 heat_mode_trigger_(new Trigger<>()),
1109 auto_mode_trigger_(new Trigger<>()),
1110 idle_action_trigger_(new Trigger<>()),
1111 off_mode_trigger_(new Trigger<>()),
1112 fan_only_action_trigger_(new Trigger<>()),
1113 fan_only_mode_trigger_(new Trigger<>()),
1114 fan_mode_on_trigger_(new Trigger<>()),
1115 fan_mode_off_trigger_(new Trigger<>()),
1116 fan_mode_auto_trigger_(new Trigger<>()),
1117 fan_mode_low_trigger_(new Trigger<>()),
1118 fan_mode_medium_trigger_(new Trigger<>()),
1119 fan_mode_high_trigger_(new Trigger<>()),
1120 fan_mode_middle_trigger_(new Trigger<>()),
1121 fan_mode_focus_trigger_(new Trigger<>()),
1122 fan_mode_diffuse_trigger_(new Trigger<>()),
1123 fan_mode_quiet_trigger_(new Trigger<>()),
1124 swing_mode_both_trigger_(new Trigger<>()),
1125 swing_mode_off_trigger_(new Trigger<>()),
1126 swing_mode_horizontal_trigger_(new Trigger<>()),
1127 swing_mode_vertical_trigger_(new Trigger<>()),
1128 temperature_change_trigger_(new Trigger<>()),
1129 preset_change_trigger_(new Trigger<>()) {}
1130
1134
1136
1138 this->on_boot_restore_from_ = on_boot_restore_from;
1139}
1141 this->set_point_minimum_differential_ = differential;
1142}
1143void ThermostatClimate::set_cool_deadband(float deadband) { this->cooling_deadband_ = deadband; }
1144void ThermostatClimate::set_cool_overrun(float overrun) { this->cooling_overrun_ = overrun; }
1145void ThermostatClimate::set_heat_deadband(float deadband) { this->heating_deadband_ = deadband; }
1146void ThermostatClimate::set_heat_overrun(float overrun) { this->heating_overrun_ = overrun; }
1151 1000 * (time < this->min_timer_duration_ ? this->min_timer_duration_ : time);
1152}
1155 1000 * (time < this->min_timer_duration_ ? this->min_timer_duration_ : time);
1156}
1159 1000 * (time < this->min_timer_duration_ ? this->min_timer_duration_ : time);
1160}
1163 1000 * (time < this->min_timer_duration_ ? this->min_timer_duration_ : time);
1164}
1167 1000 * (time < this->min_timer_duration_ ? this->min_timer_duration_ : time);
1168}
1171 1000 * (time < this->min_timer_duration_ ? this->min_timer_duration_ : time);
1172}
1175 1000 * (time < this->min_timer_duration_ ? this->min_timer_duration_ : time);
1176}
1179 1000 * (time < this->min_timer_duration_ ? this->min_timer_duration_ : time);
1180}
1183 1000 * (time < this->min_timer_duration_ ? this->min_timer_duration_ : time);
1184}
1186 this->timer_[thermostat::TIMER_IDLE_ON].time =
1187 1000 * (time < this->min_timer_duration_ ? this->min_timer_duration_ : time);
1188}
1191 this->humidity_sensor_ = humidity_sensor;
1192}
1193void ThermostatClimate::set_use_startup_delay(bool use_startup_delay) { this->use_startup_delay_ = use_startup_delay; }
1194void ThermostatClimate::set_supports_heat_cool(bool supports_heat_cool) {
1195 this->supports_heat_cool_ = supports_heat_cool;
1196}
1197void ThermostatClimate::set_supports_auto(bool supports_auto) { this->supports_auto_ = supports_auto; }
1198void ThermostatClimate::set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; }
1199void ThermostatClimate::set_supports_dry(bool supports_dry) { this->supports_dry_ = supports_dry; }
1200void ThermostatClimate::set_supports_fan_only(bool supports_fan_only) { this->supports_fan_only_ = supports_fan_only; }
1202 bool supports_fan_only_action_uses_fan_mode_timer) {
1203 this->supports_fan_only_action_uses_fan_mode_timer_ = supports_fan_only_action_uses_fan_mode_timer;
1204}
1205void ThermostatClimate::set_supports_fan_only_cooling(bool supports_fan_only_cooling) {
1206 this->supports_fan_only_cooling_ = supports_fan_only_cooling;
1207}
1208void ThermostatClimate::set_supports_fan_with_cooling(bool supports_fan_with_cooling) {
1209 this->supports_fan_with_cooling_ = supports_fan_with_cooling;
1210}
1211void ThermostatClimate::set_supports_fan_with_heating(bool supports_fan_with_heating) {
1212 this->supports_fan_with_heating_ = supports_fan_with_heating;
1213}
1214void ThermostatClimate::set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; }
1215void ThermostatClimate::set_supports_fan_mode_on(bool supports_fan_mode_on) {
1216 this->supports_fan_mode_on_ = supports_fan_mode_on;
1217}
1218void ThermostatClimate::set_supports_fan_mode_off(bool supports_fan_mode_off) {
1219 this->supports_fan_mode_off_ = supports_fan_mode_off;
1220}
1221void ThermostatClimate::set_supports_fan_mode_auto(bool supports_fan_mode_auto) {
1222 this->supports_fan_mode_auto_ = supports_fan_mode_auto;
1223}
1224void ThermostatClimate::set_supports_fan_mode_low(bool supports_fan_mode_low) {
1225 this->supports_fan_mode_low_ = supports_fan_mode_low;
1226}
1227void ThermostatClimate::set_supports_fan_mode_medium(bool supports_fan_mode_medium) {
1228 this->supports_fan_mode_medium_ = supports_fan_mode_medium;
1229}
1230void ThermostatClimate::set_supports_fan_mode_high(bool supports_fan_mode_high) {
1231 this->supports_fan_mode_high_ = supports_fan_mode_high;
1232}
1233void ThermostatClimate::set_supports_fan_mode_middle(bool supports_fan_mode_middle) {
1234 this->supports_fan_mode_middle_ = supports_fan_mode_middle;
1235}
1236void ThermostatClimate::set_supports_fan_mode_focus(bool supports_fan_mode_focus) {
1237 this->supports_fan_mode_focus_ = supports_fan_mode_focus;
1238}
1239void ThermostatClimate::set_supports_fan_mode_diffuse(bool supports_fan_mode_diffuse) {
1240 this->supports_fan_mode_diffuse_ = supports_fan_mode_diffuse;
1241}
1242void ThermostatClimate::set_supports_fan_mode_quiet(bool supports_fan_mode_quiet) {
1243 this->supports_fan_mode_quiet_ = supports_fan_mode_quiet;
1244}
1245void ThermostatClimate::set_supports_swing_mode_both(bool supports_swing_mode_both) {
1246 this->supports_swing_mode_both_ = supports_swing_mode_both;
1247}
1248void ThermostatClimate::set_supports_swing_mode_off(bool supports_swing_mode_off) {
1249 this->supports_swing_mode_off_ = supports_swing_mode_off;
1250}
1251void ThermostatClimate::set_supports_swing_mode_horizontal(bool supports_swing_mode_horizontal) {
1252 this->supports_swing_mode_horizontal_ = supports_swing_mode_horizontal;
1253}
1254void ThermostatClimate::set_supports_swing_mode_vertical(bool supports_swing_mode_vertical) {
1255 this->supports_swing_mode_vertical_ = supports_swing_mode_vertical;
1256}
1257void ThermostatClimate::set_supports_two_points(bool supports_two_points) {
1258 this->supports_two_points_ = supports_two_points;
1259}
1260
1294
1296 LOG_CLIMATE("", "Thermostat", this);
1297
1298 if (this->supports_two_points_) {
1299 ESP_LOGCONFIG(TAG, " Minimum Set Point Differential: %.1f°C", this->set_point_minimum_differential_);
1300 }
1301 ESP_LOGCONFIG(TAG, " Start-up Delay Enabled: %s", YESNO(this->use_startup_delay_));
1302 if (this->supports_cool_) {
1303 ESP_LOGCONFIG(TAG, " Cooling Parameters:");
1304 ESP_LOGCONFIG(TAG, " Deadband: %.1f°C", this->cooling_deadband_);
1305 ESP_LOGCONFIG(TAG, " Overrun: %.1f°C", this->cooling_overrun_);
1307 ESP_LOGCONFIG(TAG, " Supplemental Delta: %.1f°C", this->supplemental_cool_delta_);
1308 ESP_LOGCONFIG(TAG, " Maximum Run Time: %" PRIu32 "s",
1310 }
1311 ESP_LOGCONFIG(TAG, " Minimum Off Time: %" PRIu32 "s",
1313 ESP_LOGCONFIG(TAG, " Minimum Run Time: %" PRIu32 "s",
1315 }
1316 if (this->supports_heat_) {
1317 ESP_LOGCONFIG(TAG, " Heating Parameters:");
1318 ESP_LOGCONFIG(TAG, " Deadband: %.1f°C", this->heating_deadband_);
1319 ESP_LOGCONFIG(TAG, " Overrun: %.1f°C", this->heating_overrun_);
1321 ESP_LOGCONFIG(TAG, " Supplemental Delta: %.1f°C", this->supplemental_heat_delta_);
1322 ESP_LOGCONFIG(TAG, " Maximum Run Time: %" PRIu32 "s",
1324 }
1325 ESP_LOGCONFIG(TAG, " Minimum Off Time: %" PRIu32 "s",
1327 ESP_LOGCONFIG(TAG, " Minimum Run Time: %" PRIu32 "s",
1329 }
1330 if (this->supports_fan_only_) {
1331 ESP_LOGCONFIG(TAG, " Fanning Minimum Off Time: %" PRIu32 "s",
1333 ESP_LOGCONFIG(TAG, " Fanning Minimum Run Time: %" PRIu32 "s",
1335 }
1340 ESP_LOGCONFIG(TAG, " Minimum Fan Mode Switching Time: %" PRIu32 "s",
1342 }
1343 ESP_LOGCONFIG(TAG, " Minimum Idle Time: %" PRIu32 "s", this->timer_[thermostat::TIMER_IDLE_ON].time / 1000);
1344 ESP_LOGCONFIG(TAG, " Supports AUTO: %s", YESNO(this->supports_auto_));
1345 ESP_LOGCONFIG(TAG, " Supports HEAT/COOL: %s", YESNO(this->supports_heat_cool_));
1346 ESP_LOGCONFIG(TAG, " Supports COOL: %s", YESNO(this->supports_cool_));
1347 ESP_LOGCONFIG(TAG, " Supports DRY: %s", YESNO(this->supports_dry_));
1348 ESP_LOGCONFIG(TAG, " Supports FAN_ONLY: %s", YESNO(this->supports_fan_only_));
1349 ESP_LOGCONFIG(TAG, " Supports FAN_ONLY_ACTION_USES_FAN_MODE_TIMER: %s",
1351 ESP_LOGCONFIG(TAG, " Supports FAN_ONLY_COOLING: %s", YESNO(this->supports_fan_only_cooling_));
1352 if (this->supports_cool_) {
1353 ESP_LOGCONFIG(TAG, " Supports FAN_WITH_COOLING: %s", YESNO(this->supports_fan_with_cooling_));
1354 }
1355 if (this->supports_heat_) {
1356 ESP_LOGCONFIG(TAG, " Supports FAN_WITH_HEATING: %s", YESNO(this->supports_fan_with_heating_));
1357 }
1358 ESP_LOGCONFIG(TAG, " Supports HEAT: %s", YESNO(this->supports_heat_));
1359 ESP_LOGCONFIG(TAG, " Supports FAN MODE ON: %s", YESNO(this->supports_fan_mode_on_));
1360 ESP_LOGCONFIG(TAG, " Supports FAN MODE OFF: %s", YESNO(this->supports_fan_mode_off_));
1361 ESP_LOGCONFIG(TAG, " Supports FAN MODE AUTO: %s", YESNO(this->supports_fan_mode_auto_));
1362 ESP_LOGCONFIG(TAG, " Supports FAN MODE LOW: %s", YESNO(this->supports_fan_mode_low_));
1363 ESP_LOGCONFIG(TAG, " Supports FAN MODE MEDIUM: %s", YESNO(this->supports_fan_mode_medium_));
1364 ESP_LOGCONFIG(TAG, " Supports FAN MODE HIGH: %s", YESNO(this->supports_fan_mode_high_));
1365 ESP_LOGCONFIG(TAG, " Supports FAN MODE MIDDLE: %s", YESNO(this->supports_fan_mode_middle_));
1366 ESP_LOGCONFIG(TAG, " Supports FAN MODE FOCUS: %s", YESNO(this->supports_fan_mode_focus_));
1367 ESP_LOGCONFIG(TAG, " Supports FAN MODE DIFFUSE: %s", YESNO(this->supports_fan_mode_diffuse_));
1368 ESP_LOGCONFIG(TAG, " Supports FAN MODE QUIET: %s", YESNO(this->supports_fan_mode_quiet_));
1369 ESP_LOGCONFIG(TAG, " Supports SWING MODE BOTH: %s", YESNO(this->supports_swing_mode_both_));
1370 ESP_LOGCONFIG(TAG, " Supports SWING MODE OFF: %s", YESNO(this->supports_swing_mode_off_));
1371 ESP_LOGCONFIG(TAG, " Supports SWING MODE HORIZONTAL: %s", YESNO(this->supports_swing_mode_horizontal_));
1372 ESP_LOGCONFIG(TAG, " Supports SWING MODE VERTICAL: %s", YESNO(this->supports_swing_mode_vertical_));
1373 ESP_LOGCONFIG(TAG, " Supports TWO SET POINTS: %s", YESNO(this->supports_two_points_));
1374
1375 ESP_LOGCONFIG(TAG, " Supported PRESETS: ");
1376 for (auto &it : this->preset_config_) {
1377 const auto *preset_name = LOG_STR_ARG(climate::climate_preset_to_string(it.first));
1378
1379 ESP_LOGCONFIG(TAG, " Supports %s: %s", preset_name, YESNO(true));
1380 this->dump_preset_config_(preset_name, it.second, it.first == this->default_preset_);
1381 }
1382
1383 ESP_LOGCONFIG(TAG, " Supported CUSTOM PRESETS: ");
1384 for (auto &it : this->custom_preset_config_) {
1385 const auto *preset_name = it.first.c_str();
1386
1387 ESP_LOGCONFIG(TAG, " Supports %s: %s", preset_name, YESNO(true));
1388 this->dump_preset_config_(preset_name, it.second, it.first == this->default_custom_preset_);
1389 }
1390 ESP_LOGCONFIG(TAG, " On boot, restore from: %s",
1391 this->on_boot_restore_from_ == thermostat::DEFAULT_PRESET ? "DEFAULT_PRESET" : "MEMORY");
1392}
1393
1395
1397 : default_temperature(default_temperature) {}
1398
1400 float default_temperature_high)
1401 : default_temperature_low(default_temperature_low), default_temperature_high(default_temperature_high) {}
1402
1403} // namespace thermostat
1404} // namespace esphome
BedjetMode mode
BedJet operating mode.
void stop_action()
Stop any action connected to this trigger.
Definition automation.h:104
void trigger(Ts... x)
Inform the parent automation that the event has triggered.
Definition automation.h:96
This class is used to encode all control actions on a climate device.
Definition climate.h:33
const optional< ClimateSwingMode > & get_swing_mode() const
Definition climate.cpp:282
const optional< std::string > & get_custom_preset() const
Definition climate.cpp:281
const optional< float > & get_target_temperature_low() const
Definition climate.cpp:275
const optional< float > & get_target_temperature() const
Definition climate.cpp:274
const optional< ClimatePreset > & get_preset() const
Definition climate.cpp:280
const optional< float > & get_target_temperature_high() const
Definition climate.cpp:276
const optional< ClimateFanMode > & get_fan_mode() const
Definition climate.cpp:278
const optional< ClimateMode > & get_mode() const
Definition climate.cpp:273
ClimateMode mode
The active mode of the climate device.
Definition climate.h:173
optional< ClimateFanMode > fan_mode
The active fan mode of the climate device.
Definition climate.h:199
ClimateTraits get_traits()
Get the traits of this climate device with all overrides applied.
Definition climate.cpp:440
float target_temperature
The target temperature of the climate device.
Definition climate.h:186
float current_humidity
The current humidity of the climate device, as reported from the integration.
Definition climate.h:182
ClimateSwingMode swing_mode
The active swing mode of the climate device.
Definition climate.h:202
float target_temperature_low
The minimum target temperature of the climate device, for climate devices with split target temperatu...
Definition climate.h:189
optional< std::string > custom_preset
The active custom preset mode of the climate device.
Definition climate.h:211
float current_temperature
The current temperature of the climate device, as reported from the integration.
Definition climate.h:179
ClimateAction action
The active state of the climate device.
Definition climate.h:176
void publish_state()
Publish the state of the climate device, to be called from integrations.
Definition climate.cpp:395
optional< ClimatePreset > preset
The active preset of the climate device.
Definition climate.h:208
optional< ClimateDeviceRestoreState > restore_state_()
Restore the state of the climate device, call this from your setup() method.
Definition climate.cpp:329
float target_temperature_high
The maximum target temperature of the climate device, for climate devices with split target temperatu...
Definition climate.h:191
This class contains all static data for climate devices.
void add_supported_fan_mode(ClimateFanMode mode)
void set_supports_action(bool supports_action)
void set_supports_current_humidity(bool supports_current_humidity)
void add_supported_custom_preset(const std::string &preset)
void add_supported_preset(ClimatePreset preset)
void set_supports_two_point_target_temperature(bool supports_two_point_target_temperature)
void add_supported_mode(ClimateMode mode)
void set_supports_current_temperature(bool supports_current_temperature)
void add_supported_swing_mode(ClimateSwingMode mode)
bool has_value() const
Definition optional.h:87
value_type value_or(U const &v) const
Definition optional.h:93
value_type const & value() const
Definition optional.h:89
Base-class for all sensors.
Definition sensor.h:57
void add_on_state_callback(std::function< void(float)> &&callback)
Add a callback that will be called every time a filtered value arrives.
Definition sensor.cpp:52
float state
This member variable stores the last state that has passed through all filters.
Definition sensor.h:131
Trigger * swing_mode_off_trigger_
The trigger to call when the controller should switch the swing mode to "off".
void set_supports_swing_mode_horizontal(bool supports_swing_mode_horizontal)
Trigger * idle_action_trigger_
The trigger to call when the controller should switch to idle action/off mode.
void switch_to_action_(climate::ClimateAction action, bool publish_state=true)
Switch the climate device to the given climate action.
void set_supports_fan_mode_on(bool supports_fan_mode_on)
Trigger * preset_change_trigger_
The triggr to call when the preset mode changes.
float cooling_deadband_
Hysteresis values used for computing climate actions.
Trigger * heat_action_trigger_
The trigger to call when the controller should switch to heating action/mode.
thermostat::OnBootRestoreFrom on_boot_restore_from_
If set to DEFAULT_PRESET then the default preset is always used.
void control(const climate::ClimateCall &call) override
Override control to change settings of the climate device.
bool use_startup_delay_
Used to start "off" delay timers at boot.
float cool_deadband()
Get current hysteresis values.
bool climate_action_change_delayed()
Returns true if a climate action/fan mode transition is being delayed.
void set_supports_fan_with_heating(bool supports_fan_with_heating)
bool cooling_max_runtime_exceeded_
Flags indicating if maximum allowable run time was exceeded.
const uint8_t min_timer_duration_
Minimum allowable duration in seconds for action timers.
Trigger * fan_mode_low_trigger_
The trigger to call when the controller should switch the fan to "low" speed.
void set_supports_two_points(bool supports_two_points)
Trigger * fan_mode_auto_trigger_
The trigger to call when the controller should switch the fan to "auto" mode.
void set_supports_fan_only_cooling(bool supports_fan_only_cooling)
bool supports_fan_mode_on_
Whether the controller supports turning on or off just the fan.
void set_supports_fan_only_action_uses_fan_mode_timer(bool fan_only_action_uses_fan_mode_timer)
float set_point_minimum_differential_
Minimum differential required between set points.
bool supports_fan_with_cooling_
Special flags – enables fan_only action to be called with cooling/heating actions.
void set_supports_fan_mode_diffuse(bool supports_fan_mode_diffuse)
void switch_to_swing_mode_(climate::ClimateSwingMode swing_mode, bool publish_state=true)
Switch the climate device to the given climate swing mode.
Trigger * fan_mode_diffuse_trigger_
The trigger to call when the controller should switch the fan to "diffuse" position.
Trigger * fan_only_action_trigger_
The trigger to call when the controller should switch to fan-only action/mode.
Trigger * cool_action_trigger_
The trigger to call when the controller should switch to cooling action/mode.
Trigger * swing_mode_vertical_trigger_
The trigger to call when the controller should switch the swing mode to "vertical".
std::vector< ThermostatClimateTimer > timer_
Climate action timers.
bool change_preset_internal_(const ThermostatClimateTargetTempConfig &config)
Applies the temperature, mode, fan, and swing modes of the provided config.
bool hysteresis_valid()
Set point and hysteresis validation.
void set_supports_fan_mode_auto(bool supports_fan_mode_auto)
void switch_to_supplemental_action_(climate::ClimateAction action)
Trigger * dry_action_trigger_
The trigger to call when the controller should switch to dry (dehumidification) mode.
void switch_to_mode_(climate::ClimateMode mode, bool publish_state=true)
Switch the climate device to the given climate mode.
Trigger * swing_mode_both_trigger_
The trigger to call when the controller should switch the swing mode to "both".
void set_supports_swing_mode_vertical(bool supports_swing_mode_vertical)
void set_supports_fan_only(bool supports_fan_only)
bool supports_fan_only_action_uses_fan_mode_timer_
Special flag – enables fan_modes to share timer with fan_only climate action.
void set_supports_swing_mode_off(bool supports_swing_mode_off)
void switch_to_fan_mode_(climate::ClimateFanMode fan_mode, bool publish_state=true)
Switch the climate device to the given climate fan mode.
bool supports_swing_mode_both_
Whether the controller supports various swing modes.
climate::ClimateTraits traits() override
Return the traits of this controller.
Trigger * swing_mode_horizontal_trigger_
The trigger to call when the controller should switch the swing mode to "horizontal".
Trigger * fan_mode_focus_trigger_
The trigger to call when the controller should switch the fan to "focus" position.
climate::ClimateFanMode locked_fan_mode()
Returns the fan mode that is locked in (check fan_mode_change_delayed(), first!)
void set_humidity_sensor(sensor::Sensor *humidity_sensor)
void set_supports_fan_mode_middle(bool supports_fan_mode_middle)
Trigger * temperature_change_trigger_
The trigger to call when the target temperature(s) change(es).
void set_supports_fan_mode_low(bool supports_fan_mode_low)
Trigger * fan_mode_off_trigger_
The trigger to call when the controller should switch off the fan.
bool timer_active_(ThermostatClimateTimerIndex timer_index)
float supplemental_cool_delta_
Maximum allowable temperature deltas before engauging supplemental cooling/heating actions.
std::map< std::string, ThermostatClimateTargetTempConfig > custom_preset_config_
The set of custom preset configurations this thermostat supports (eg. "My Custom Preset")
void set_supports_heat_cool(bool supports_heat_cool)
void set_supports_fan_mode_quiet(bool supports_fan_mode_quiet)
climate::ClimateAction delayed_climate_action()
Returns the climate action that is being delayed (check climate_action_change_delayed(),...
sensor::Sensor * sensor_
The sensor used for getting the current temperature.
void set_supports_fan_mode_medium(bool supports_fan_mode_medium)
void set_on_boot_restore_from(thermostat::OnBootRestoreFrom on_boot_restore_from)
uint32_t timer_duration_(ThermostatClimateTimerIndex timer_index)
void set_supports_swing_mode_both(bool supports_swing_mode_both)
void start_timer_(ThermostatClimateTimerIndex timer_index)
Start/cancel/get status of climate action timer.
Trigger * fan_mode_high_trigger_
The trigger to call when the controller should switch the fan to "high" speed.
void dump_preset_config_(const char *preset_name, const ThermostatClimateTargetTempConfig &config, bool is_default_preset)
void set_set_point_minimum_differential(float differential)
void set_custom_preset_config(const std::string &name, const ThermostatClimateTargetTempConfig &config)
bool supports_fan_mode_low_
Whether the controller supports various fan speeds and/or positions.
bool supports_fan_only_cooling_
Special flag – enables fan to be switched based on target_temperature_high.
Trigger * prev_action_trigger_
A reference to the trigger that was previously active.
bool supports_auto_
Whether the controller supports auto/cooling/drying/fanning/heating.
climate::ClimateAction supplemental_action_
Store previously-known states.
void set_fan_mode_minimum_switching_time_in_sec(uint32_t time)
void set_preset_config(climate::ClimatePreset preset, const ThermostatClimateTargetTempConfig &config)
void set_supports_fan_with_cooling(bool supports_fan_with_cooling)
Trigger * fan_mode_medium_trigger_
The trigger to call when the controller should switch the fan to "medium" speed.
Trigger * fan_mode_middle_trigger_
The trigger to call when the controller should switch the fan to "middle" position.
void set_supports_fan_mode_focus(bool supports_fan_mode_focus)
void check_temperature_change_trigger_()
Check if the temperature change trigger should be called.
Trigger * fan_mode_on_trigger_
The trigger to call when the controller should switch on the fan.
void set_supports_fan_mode_off(bool supports_fan_mode_off)
void set_use_startup_delay(bool use_startup_delay)
void change_custom_preset_(const std::string &custom_preset)
Change to a provided custom preset setting; will reset temperature, mode, fan, and swing modes accord...
bool cancel_timer_(ThermostatClimateTimerIndex timer_index)
climate::ClimateAction compute_supplemental_action_()
float prev_target_temperature_
Store previously-known temperatures.
climate::ClimatePreset default_preset_
Default standard preset to use on start up.
sensor::Sensor * humidity_sensor_
The sensor used for getting the current humidity.
void cooling_max_run_time_timer_callback_()
set_timeout() callbacks for various actions (see above)
bool supports_fan_mode_auto_
Whether the controller supports fan auto mode.
climate::ClimateAction compute_action_(bool ignore_timers=false)
Re-compute the required action of this climate controller.
std::map< climate::ClimatePreset, ThermostatClimateTargetTempConfig > preset_config_
The set of standard preset configurations this thermostat supports (Eg. AWAY, ECO,...
bool supports_two_points_
Whether the controller supports two set points.
std::string default_custom_preset_
Default custom preset to use on start up.
bool setup_complete_
setup_complete_ blocks modifying/resetting the temps immediately after boot
void set_supports_fan_mode_high(bool supports_fan_mode_high)
bool idle_action_ready_()
Is the action ready to be called? Returns true if so.
void change_preset_(climate::ClimatePreset preset)
Change to a provided preset setting; will reset temperature, mode, fan, and swing modes accordingly.
void refresh()
Call triggers based on updated climate states (modes/actions)
void set_default_preset(const std::string &custom_preset)
Trigger * fan_mode_quiet_trigger_
The trigger to call when the controller should switch the fan to "quiet" position.
std::function< void()> timer_cbf_(ThermostatClimateTimerIndex timer_index)
Trigger * auto_mode_trigger_
The trigger to call when the controller should switch to auto mode.
bool cooling_required_()
Check if cooling/fanning/heating actions are required; returns true if so.
ClimateSwingMode swing_mode
Definition climate.h:11
uint8_t custom_preset
Definition climate.h:9
ClimateFanMode fan_mode
Definition climate.h:3
ClimatePreset preset
Definition climate.h:8
bool state
Definition fan.h:0
const LogString * climate_swing_mode_to_string(ClimateSwingMode swing_mode)
Convert the given ClimateSwingMode to a human-readable string.
const LogString * climate_preset_to_string(ClimatePreset preset)
Convert the given PresetMode to a human-readable string.
ClimatePreset
Enum for all preset modes.
@ CLIMATE_PRESET_NONE
No preset is active.
const LogString * climate_fan_mode_to_string(ClimateFanMode fan_mode)
Convert the given ClimateFanMode to a human-readable string.
ClimateSwingMode
Enum for all modes a climate swing can be in.
@ 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.
ClimateAction
Enum for the current action of the climate device. Values match those of ClimateMode.
@ CLIMATE_ACTION_OFF
The climate device is off (inactive or no power)
@ CLIMATE_ACTION_IDLE
The climate device is idle (monitoring climate but no action needed)
@ CLIMATE_ACTION_DRYING
The climate device is drying.
@ CLIMATE_ACTION_HEATING
The climate device is actively heating.
@ CLIMATE_ACTION_COOLING
The climate device is actively cooling.
@ CLIMATE_ACTION_FAN
The climate device is in fan only mode.
@ 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.
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:27
optional< climate::ClimateSwingMode > swing_mode_
uint16_t temperature
Definition sun_gtil2.cpp:12