ESPHome 2026.5.0-dev
Loading...
Searching...
No Matches
climate_traits.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstring>
4#include <vector>
5#include "climate_mode.h"
8
9namespace esphome::climate {
10
11// Type aliases for climate enum bitmasks
12// These replace std::set<EnumType> to eliminate red-black tree overhead
13// For contiguous enums starting at 0, DefaultBitPolicy provides 1:1 mapping (enum value = bit position)
14// Bitmask size is automatically calculated from the last enum value
20
21// Lightweight linear search for small vectors (1-20 items) of const char* pointers
22// Avoids std::find template overhead
23inline bool vector_contains(const std::vector<const char *> &vec, const char *value, size_t len) {
24 for (const char *item : vec) {
25 if (strncmp(item, value, len) == 0 && item[len] == '\0')
26 return true;
27 }
28 return false;
29}
30
31inline bool vector_contains(const std::vector<const char *> &vec, const char *value) {
32 return vector_contains(vec, value, strlen(value));
33}
34
35// Find and return matching pointer from vector, or nullptr if not found
36inline const char *vector_find(const std::vector<const char *> &vec, const char *value, size_t len) {
37 for (const char *item : vec) {
38 if (strncmp(item, value, len) == 0 && item[len] == '\0')
39 return item;
40 }
41 return nullptr;
42}
43
71class Climate; // Forward declaration
72
74 friend class Climate; // Allow Climate to access protected find methods
75
76 public:
78 uint32_t get_feature_flags() const { return this->feature_flags_; }
79 void add_feature_flags(uint32_t feature_flags) { this->feature_flags_ |= feature_flags; }
80 void clear_feature_flags(uint32_t feature_flags) { this->feature_flags_ &= ~feature_flags; }
81 bool has_feature_flags(uint32_t feature_flags) const { return this->feature_flags_ & feature_flags; }
82 void set_feature_flags(uint32_t feature_flags) { this->feature_flags_ = feature_flags; }
83
84 ESPDEPRECATED("This method is deprecated, use get_feature_flags() instead", "2025.11.0")
85 bool get_supports_current_temperature() const {
87 }
88 ESPDEPRECATED("This method is deprecated, use add_feature_flags() instead", "2025.11.0")
89 void set_supports_current_temperature(bool supports_current_temperature) {
90 if (supports_current_temperature) {
92 } else {
94 }
95 }
96 ESPDEPRECATED("This method is deprecated, use get_feature_flags() instead", "2025.11.0")
97 bool get_supports_current_humidity() const { return this->has_feature_flags(CLIMATE_SUPPORTS_CURRENT_HUMIDITY); }
98 ESPDEPRECATED("This method is deprecated, use add_feature_flags() instead", "2025.11.0")
99 void set_supports_current_humidity(bool supports_current_humidity) {
100 if (supports_current_humidity) {
102 } else {
104 }
105 }
106 ESPDEPRECATED("This method is deprecated, use get_feature_flags() instead", "2025.11.0")
107 bool get_supports_two_point_target_temperature() const {
109 }
110 ESPDEPRECATED("This method is deprecated, use add_feature_flags() instead", "2025.11.0")
111 void set_supports_two_point_target_temperature(bool supports_two_point_target_temperature) {
112 if (supports_two_point_target_temperature)
113 // Use CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE to mimic previous behavior
114 {
116 } else {
118 }
119 }
120 ESPDEPRECATED("This method is deprecated, use get_feature_flags() instead", "2025.11.0")
121 bool get_supports_target_humidity() const { return this->has_feature_flags(CLIMATE_SUPPORTS_TARGET_HUMIDITY); }
122 ESPDEPRECATED("This method is deprecated, use add_feature_flags() instead", "2025.11.0")
123 void set_supports_target_humidity(bool supports_target_humidity) {
124 if (supports_target_humidity) {
126 } else {
128 }
129 }
130 ESPDEPRECATED("This method is deprecated, use get_feature_flags() instead", "2025.11.0")
131 bool get_supports_action() const { return this->has_feature_flags(CLIMATE_SUPPORTS_ACTION); }
132 ESPDEPRECATED("This method is deprecated, use add_feature_flags() instead", "2025.11.0")
133 void set_supports_action(bool supports_action) {
134 if (supports_action) {
136 } else {
138 }
139 }
140
143 bool supports_mode(ClimateMode mode) const { return this->supported_modes_.count(mode); }
144 const ClimateModeMask &get_supported_modes() const { return this->supported_modes_; }
145
150 if (!this->supported_fan_modes_.empty()) {
151 return true;
152 }
153 // Same precedence as get_supported_custom_fan_modes() getter
154 if (this->supported_custom_fan_modes_) {
155 return !this->supported_custom_fan_modes_->empty();
156 }
157 return !this->compat_custom_fan_modes_.empty(); // Compat: remove in 2026.11.0
158 }
160
161 // Remove before 2026.11.0
162 ESPDEPRECATED("Call set_supported_custom_fan_modes() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0")
163 void set_supported_custom_fan_modes(std::initializer_list<const char *> modes) {
164 // Compat: store in owned vector. Copies copy the vector (deprecated path still copies this vector).
165 this->compat_custom_fan_modes_ = modes;
166 }
167 // Remove before 2026.11.0
168 ESPDEPRECATED("Call set_supported_custom_fan_modes() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0")
169 void set_supported_custom_fan_modes(const std::vector<const char *> &modes) {
170 this->compat_custom_fan_modes_ = modes;
171 }
172 // Remove before 2026.11.0
173 template<size_t N>
174 ESPDEPRECATED("Call set_supported_custom_fan_modes() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0")
175 void set_supported_custom_fan_modes(const char *const (&modes)[N]) {
176 this->compat_custom_fan_modes_.assign(modes, modes + N);
177 }
178
179 // Deleted overloads to catch incorrect std::string usage at compile time with clear error messages
180 void set_supported_custom_fan_modes(const std::vector<std::string> &modes) = delete;
181 void set_supported_custom_fan_modes(std::initializer_list<std::string> modes) = delete;
182
183 // Compat: returns const ref with empty fallback. In 2026.11.0 change to return const vector *.
184 const std::vector<const char *> &get_supported_custom_fan_modes() const;
186 return (this->supported_custom_fan_modes_ &&
187 vector_contains(*this->supported_custom_fan_modes_, custom_fan_mode)) ||
188 vector_contains(this->compat_custom_fan_modes_, custom_fan_mode); // Compat: remove in 2026.11.0
189 }
190 bool supports_custom_fan_mode(const std::string &custom_fan_mode) const {
191 return this->supports_custom_fan_mode(custom_fan_mode.c_str());
192 }
193
196 bool supports_preset(ClimatePreset preset) const { return this->supported_presets_.count(preset); }
197 bool get_supports_presets() const { return !this->supported_presets_.empty(); }
199
200 // Remove before 2026.11.0
201 ESPDEPRECATED("Call set_supported_custom_presets() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0")
202 void set_supported_custom_presets(std::initializer_list<const char *> presets) {
203 this->compat_custom_presets_ = presets;
204 }
205 // Remove before 2026.11.0
206 ESPDEPRECATED("Call set_supported_custom_presets() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0")
207 void set_supported_custom_presets(const std::vector<const char *> &presets) {
208 this->compat_custom_presets_ = presets;
209 }
210 // Remove before 2026.11.0
211 template<size_t N>
212 ESPDEPRECATED("Call set_supported_custom_presets() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0")
213 void set_supported_custom_presets(const char *const (&presets)[N]) {
214 this->compat_custom_presets_.assign(presets, presets + N);
215 }
216
217 // Deleted overloads to catch incorrect std::string usage at compile time with clear error messages
218 void set_supported_custom_presets(const std::vector<std::string> &presets) = delete;
219 void set_supported_custom_presets(std::initializer_list<std::string> presets) = delete;
220
221 // Compat: returns const ref with empty fallback. In 2026.11.0 change to return const vector *.
222 const std::vector<const char *> &get_supported_custom_presets() const;
223 bool supports_custom_preset(const char *custom_preset) const {
224 return (this->supported_custom_presets_ && vector_contains(*this->supported_custom_presets_, custom_preset)) ||
225 vector_contains(this->compat_custom_presets_, custom_preset); // Compat: remove in 2026.11.0
226 }
227 bool supports_custom_preset(const std::string &custom_preset) const {
228 return this->supports_custom_preset(custom_preset.c_str());
229 }
230
234 bool get_supports_swing_modes() const { return !this->supported_swing_modes_.empty(); }
236
238 void set_visual_min_temperature(float visual_min_temperature) {
239 this->visual_min_temperature_ = visual_min_temperature;
240 }
242 void set_visual_max_temperature(float visual_max_temperature) {
243 this->visual_max_temperature_ = visual_max_temperature;
244 }
247 void set_visual_target_temperature_step(float temperature_step) {
248 this->visual_target_temperature_step_ = temperature_step;
249 }
250 void set_visual_current_temperature_step(float temperature_step) {
251 this->visual_current_temperature_step_ = temperature_step;
252 }
253 void set_visual_temperature_step(float temperature_step) {
254 this->visual_target_temperature_step_ = temperature_step;
255 this->visual_current_temperature_step_ = temperature_step;
256 }
259
260 float get_visual_min_humidity() const { return this->visual_min_humidity_; }
261 void set_visual_min_humidity(float visual_min_humidity) { this->visual_min_humidity_ = visual_min_humidity; }
262 float get_visual_max_humidity() const { return this->visual_max_humidity_; }
263 void set_visual_max_humidity(float visual_max_humidity) { this->visual_max_humidity_ = visual_max_humidity; }
264
265 protected:
267 if (supported) {
268 this->supported_modes_.insert(mode);
269 } else {
270 this->supported_modes_.erase(mode);
271 }
272 }
274 if (supported) {
275 this->supported_fan_modes_.insert(mode);
276 } else {
277 this->supported_fan_modes_.erase(mode);
278 }
279 }
281 if (supported) {
282 this->supported_swing_modes_.insert(mode);
283 } else {
284 this->supported_swing_modes_.erase(mode);
285 }
286 }
287
289 void set_supported_custom_fan_modes_(const std::vector<const char *> *modes) {
290 this->supported_custom_fan_modes_ = modes;
291 }
292 void set_supported_custom_presets_(const std::vector<const char *> *presets) {
293 this->supported_custom_presets_ = presets;
294 }
295
298 const char *find_custom_fan_mode_(const char *custom_fan_mode) const {
299 return this->find_custom_fan_mode_(custom_fan_mode, strlen(custom_fan_mode));
300 }
301 const char *find_custom_fan_mode_(const char *custom_fan_mode, size_t len) const {
302 if (this->supported_custom_fan_modes_) {
303 return vector_find(*this->supported_custom_fan_modes_, custom_fan_mode, len);
304 }
305 // Compat: check owned vector from deprecated setters. Remove in 2026.11.0.
306 return vector_find(this->compat_custom_fan_modes_, custom_fan_mode, len);
307 }
308
311 const char *find_custom_preset_(const char *custom_preset) const {
312 return this->find_custom_preset_(custom_preset, strlen(custom_preset));
313 }
314 const char *find_custom_preset_(const char *custom_preset, size_t len) const {
315 if (this->supported_custom_presets_) {
316 return vector_find(*this->supported_custom_presets_, custom_preset, len);
317 }
318 // Compat: check owned vector from deprecated setters. Remove in 2026.11.0.
319 return vector_find(this->compat_custom_presets_, custom_preset, len);
320 }
321
329
334
340 const std::vector<const char *> *supported_custom_fan_modes_{nullptr};
341 const std::vector<const char *> *supported_custom_presets_{nullptr};
342 // Compat: owned storage for deprecated setters. Copies copy the vector (copies include this vector).
343 // Remove in 2026.11.0.
344 std::vector<const char *> compat_custom_fan_modes_;
345 std::vector<const char *> compat_custom_presets_;
346};
347
348} // namespace esphome::climate
BedjetMode mode
BedJet operating mode.
constexpr size_t count(ValueType value) const
Check if the set contains a specific value (std::set compatibility) Returns 1 if present,...
constexpr void insert(ValueType value)
Add a single value to the set (std::set compatibility)
constexpr void erase(ValueType value)
Remove a value from the set (std::set compatibility)
constexpr bool empty() const
Check if the set is empty.
ClimateDevice - This is the base class for all climate integrations.
Definition climate.h:187
ESPDEPRECATED("Call set_supported_custom_presets() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0") void set_supported_custom_presets(const std
void set_visual_max_temperature(float visual_max_temperature)
ESPDEPRECATED("Call set_supported_custom_fan_modes() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0") void set_supported_custom_fan_modes(const std
const char * find_custom_fan_mode_(const char *custom_fan_mode, size_t len) const
void add_feature_flags(uint32_t feature_flags)
ESPDEPRECATED("This method is deprecated, use add_feature_flags() instead", "2025.11.0") void set_supports_current_humidity(bool supports_current_humidity)
void add_supported_fan_mode(ClimateFanMode mode)
const ClimatePresetMask & get_supported_presets() const
ESPDEPRECATED("This method is deprecated, use add_feature_flags() instead", "2025.11.0") void set_supports_current_temperature(bool supports_current_temperature)
ESPDEPRECATED("This method is deprecated, use add_feature_flags() instead", "2025.11.0") void set_supports_target_humidity(bool supports_target_humidity)
void set_supported_custom_presets(const std::vector< std::string > &presets)=delete
void set_supported_custom_fan_modes(std::initializer_list< std::string > modes)=delete
const std::vector< const char * > * supported_custom_presets_
const std::vector< const char * > & get_supported_custom_fan_modes() const
const ClimateSwingModeMask & get_supported_swing_modes() const
void set_visual_temperature_step(float temperature_step)
void add_supported_preset(ClimatePreset preset)
const std::vector< const char * > * supported_custom_fan_modes_
Custom mode storage - pointers to vectors owned by the Climate base class.
ESPDEPRECATED("Call set_supported_custom_presets() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0") void set_supported_custom_presets(std
void set_visual_target_temperature_step(float temperature_step)
ESPDEPRECATED("This method is deprecated, use add_feature_flags() instead", "2025.11.0") void set_supports_two_point_target_temperature(bool supports_two_point_target_temperature)
ESPDEPRECATED("This method is deprecated, use add_feature_flags() instead", "2025.11.0") void set_supports_action(bool supports_action)
float get_visual_current_temperature_step() const
void set_supported_presets(ClimatePresetMask presets)
void set_supported_swing_modes(ClimateSwingModeMask modes)
void set_visual_min_temperature(float visual_min_temperature)
bool supports_mode(ClimateMode mode) const
int8_t get_target_temperature_accuracy_decimals() const
const ClimateFanModeMask & get_supported_fan_modes() const
float get_visual_target_temperature_step() const
void set_supported_custom_presets_(const std::vector< const char * > *presets)
void set_visual_min_humidity(float visual_min_humidity)
ESPDEPRECATED("This method is deprecated, use get_feature_flags() instead", "2025.11.0") bool get_supports_two_point_target_temperature() const
bool supports_custom_preset(const std::string &custom_preset) const
ESPDEPRECATED("This method is deprecated, use get_feature_flags() instead", "2025.11.0") bool get_supports_current_temperature() const
void set_visual_current_temperature_step(float temperature_step)
bool supports_custom_fan_mode(const char *custom_fan_mode) const
const char * find_custom_preset_(const char *custom_preset, size_t len) const
ESPDEPRECATED("Call set_supported_custom_fan_modes() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0") void set_supported_custom_fan_modes(const char *const (&modes)[N])
void set_supported_custom_presets(std::initializer_list< std::string > presets)=delete
void set_supported_modes(ClimateModeMask modes)
climate::ClimateFanModeMask supported_fan_modes_
bool supports_custom_preset(const char *custom_preset) const
void set_supported_custom_fan_modes_(const std::vector< const char * > *modes)
Set custom mode pointers (only Climate::get_traits() should call these).
climate::ClimateSwingModeMask supported_swing_modes_
ESPDEPRECATED("This method is deprecated, use get_feature_flags() instead", "2025.11.0") bool get_supports_action() const
bool has_feature_flags(uint32_t feature_flags) const
ESPDEPRECATED("Call set_supported_custom_presets() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0") void set_supported_custom_presets(const char *const (&presets)[N])
climate::ClimatePresetMask supported_presets_
int8_t get_current_temperature_accuracy_decimals() const
void set_visual_max_humidity(float visual_max_humidity)
ESPDEPRECATED("This method is deprecated, use get_feature_flags() instead", "2025.11.0") bool get_supports_target_humidity() const
bool supports_fan_mode(ClimateFanMode fan_mode) const
ESPDEPRECATED("This method is deprecated, use get_feature_flags() instead", "2025.11.0") bool get_supports_current_humidity() const
void add_supported_mode(ClimateMode mode)
void set_feature_flags(uint32_t feature_flags)
bool supports_custom_fan_mode(const std::string &custom_fan_mode) const
void set_swing_mode_support_(climate::ClimateSwingMode mode, bool supported)
void clear_feature_flags(uint32_t feature_flags)
climate::ClimateModeMask supported_modes_
bool supports_preset(ClimatePreset preset) const
void set_supported_fan_modes(ClimateFanModeMask modes)
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...
ESPDEPRECATED("Call set_supported_custom_fan_modes() on the Climate entity instead. Removed in 2026.11.0", "2026.5.0") void set_supported_custom_fan_modes(std
const std::vector< const char * > & get_supported_custom_presets() const
void set_fan_mode_support_(climate::ClimateFanMode mode, bool supported)
const ClimateModeMask & get_supported_modes() const
void add_supported_swing_mode(ClimateSwingMode mode)
uint32_t get_feature_flags() const
Get/set feature flags (see ClimateFeatures enum in climate_mode.h)
void set_supported_custom_fan_modes(const std::vector< std::string > &modes)=delete
std::vector< const char * > compat_custom_presets_
bool supports_swing_mode(ClimateSwingMode swing_mode) const
std::vector< const char * > compat_custom_fan_modes_
void set_mode_support_(climate::ClimateMode mode, bool supported)
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
uint8_t custom_fan_mode
Definition climate.h:4
bool vector_contains(const std::vector< const char * > &vec, const char *value, size_t len)
@ CLIMATE_SUPPORTS_CURRENT_HUMIDITY
@ CLIMATE_SUPPORTS_CURRENT_TEMPERATURE
@ CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE
ClimatePreset
Enum for all preset modes NOTE: If adding values, update ClimatePresetMask in climate_traits....
ClimateSwingMode
Enum for all modes a climate swing can be in NOTE: If adding values, update ClimateSwingModeMask in c...
ClimateMode
Enum for all modes a climate device can be in.
@ CLIMATE_MODE_OFF
The climate device is off.
ClimateFanMode
NOTE: If adding values, update ClimateFanModeMask in climate_traits.h to use the new last value.
const char * vector_find(const std::vector< const char * > &vec, const char *value, size_t len)
std::string size_t len
Definition helpers.h:1045
static void uint32_t