mirror of
https://github.com/esphome/esphome.git
synced 2025-10-29 14:13:51 +00:00
265 lines
12 KiB
C++
265 lines
12 KiB
C++
#pragma once
|
|
|
|
#include <vector>
|
|
#include "climate_mode.h"
|
|
#include "climate_mode_bitmask.h"
|
|
#include "esphome/core/helpers.h"
|
|
|
|
namespace esphome {
|
|
namespace climate {
|
|
|
|
// Lightweight linear search for small vectors (1-20 items)
|
|
// Avoids std::find template overhead
|
|
template<typename T> inline bool vector_contains(const std::vector<T> &vec, const T &value) {
|
|
for (const auto &item : vec) {
|
|
if (item == value)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
} // namespace climate
|
|
} // namespace esphome
|
|
|
|
namespace esphome {
|
|
|
|
#ifdef USE_API
|
|
namespace api {
|
|
class APIConnection;
|
|
} // namespace api
|
|
#endif
|
|
|
|
namespace climate {
|
|
|
|
/** This class contains all static data for climate devices.
|
|
*
|
|
* All climate devices must support these features:
|
|
* - OFF mode
|
|
* - Target Temperature
|
|
*
|
|
* All other properties and modes are optional and the integration must mark
|
|
* each of them as supported by setting the appropriate flag(s) here.
|
|
*
|
|
* - feature flags: see ClimateFeatures enum in climate_mode.h
|
|
* - supports modes:
|
|
* - auto mode (automatic control)
|
|
* - cool mode (lowers current temperature)
|
|
* - heat mode (increases current temperature)
|
|
* - dry mode (removes humidity from air)
|
|
* - fan mode (only turns on fan)
|
|
* - supports fan modes - optionally, if it has a fan which can be configured in different ways:
|
|
* - on, off, auto, high, medium, low, middle, focus, diffuse, quiet
|
|
* - supports swing modes - optionally, if it has a swing which can be configured in different ways:
|
|
* - off, both, vertical, horizontal
|
|
*
|
|
* This class also contains static data for the climate device display:
|
|
* - visual min/max temperature/humidity - tells the frontend what range of temperature/humidity the
|
|
* climate device should display (gauge min/max values)
|
|
* - temperature step - the step with which to increase/decrease target temperature.
|
|
* This also affects with how many decimal places the temperature is shown
|
|
*/
|
|
class ClimateTraits {
|
|
public:
|
|
/// Get/set feature flags (see ClimateFeatures enum in climate_mode.h)
|
|
uint32_t get_feature_flags() const { return this->feature_flags_; }
|
|
void add_feature_flags(uint32_t feature_flags) { this->feature_flags_ |= feature_flags; }
|
|
void clear_feature_flags(uint32_t feature_flags) { this->feature_flags_ &= ~feature_flags; }
|
|
bool has_feature_flags(uint32_t feature_flags) const { return this->feature_flags_ & feature_flags; }
|
|
void set_feature_flags(uint32_t feature_flags) { this->feature_flags_ = feature_flags; }
|
|
|
|
ESPDEPRECATED("This method is deprecated, use get_feature_flags() instead", "2025.11.0")
|
|
bool get_supports_current_temperature() const {
|
|
return this->has_feature_flags(CLIMATE_SUPPORTS_CURRENT_TEMPERATURE);
|
|
}
|
|
ESPDEPRECATED("This method is deprecated, use add_feature_flags() instead", "2025.11.0")
|
|
void set_supports_current_temperature(bool supports_current_temperature) {
|
|
if (supports_current_temperature) {
|
|
this->add_feature_flags(CLIMATE_SUPPORTS_CURRENT_TEMPERATURE);
|
|
} else {
|
|
this->clear_feature_flags(CLIMATE_SUPPORTS_CURRENT_TEMPERATURE);
|
|
}
|
|
}
|
|
ESPDEPRECATED("This method is deprecated, use get_feature_flags() instead", "2025.11.0")
|
|
bool get_supports_current_humidity() const { return this->has_feature_flags(CLIMATE_SUPPORTS_CURRENT_HUMIDITY); }
|
|
ESPDEPRECATED("This method is deprecated, use add_feature_flags() instead", "2025.11.0")
|
|
void set_supports_current_humidity(bool supports_current_humidity) {
|
|
if (supports_current_humidity) {
|
|
this->add_feature_flags(CLIMATE_SUPPORTS_CURRENT_HUMIDITY);
|
|
} else {
|
|
this->clear_feature_flags(CLIMATE_SUPPORTS_CURRENT_HUMIDITY);
|
|
}
|
|
}
|
|
ESPDEPRECATED("This method is deprecated, use get_feature_flags() instead", "2025.11.0")
|
|
bool get_supports_two_point_target_temperature() const {
|
|
return this->has_feature_flags(CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE);
|
|
}
|
|
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) {
|
|
if (supports_two_point_target_temperature)
|
|
// Use CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE to mimic previous behavior
|
|
{
|
|
this->add_feature_flags(CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE);
|
|
} else {
|
|
this->clear_feature_flags(CLIMATE_REQUIRES_TWO_POINT_TARGET_TEMPERATURE);
|
|
}
|
|
}
|
|
ESPDEPRECATED("This method is deprecated, use get_feature_flags() instead", "2025.11.0")
|
|
bool get_supports_target_humidity() const { return this->has_feature_flags(CLIMATE_SUPPORTS_TARGET_HUMIDITY); }
|
|
ESPDEPRECATED("This method is deprecated, use add_feature_flags() instead", "2025.11.0")
|
|
void set_supports_target_humidity(bool supports_target_humidity) {
|
|
if (supports_target_humidity) {
|
|
this->add_feature_flags(CLIMATE_SUPPORTS_TARGET_HUMIDITY);
|
|
} else {
|
|
this->clear_feature_flags(CLIMATE_SUPPORTS_TARGET_HUMIDITY);
|
|
}
|
|
}
|
|
ESPDEPRECATED("This method is deprecated, use get_feature_flags() instead", "2025.11.0")
|
|
bool get_supports_action() const { return this->has_feature_flags(CLIMATE_SUPPORTS_ACTION); }
|
|
ESPDEPRECATED("This method is deprecated, use add_feature_flags() instead", "2025.11.0")
|
|
void set_supports_action(bool supports_action) {
|
|
if (supports_action) {
|
|
this->add_feature_flags(CLIMATE_SUPPORTS_ACTION);
|
|
} else {
|
|
this->clear_feature_flags(CLIMATE_SUPPORTS_ACTION);
|
|
}
|
|
}
|
|
|
|
void set_supported_modes(ClimateModeMask modes) { this->supported_modes_ = modes; }
|
|
void set_supported_modes(std::initializer_list<ClimateMode> modes) {
|
|
this->supported_modes_ = ClimateModeMask(modes);
|
|
}
|
|
void add_supported_mode(ClimateMode mode) { this->supported_modes_.add(mode); }
|
|
bool supports_mode(ClimateMode mode) const { return this->supported_modes_.contains(mode); }
|
|
const ClimateModeMask &get_supported_modes() const { return this->supported_modes_; }
|
|
|
|
void set_supported_fan_modes(ClimateFanModeMask modes) { this->supported_fan_modes_ = modes; }
|
|
void set_supported_fan_modes(std::initializer_list<ClimateFanMode> modes) {
|
|
this->supported_fan_modes_ = ClimateFanModeMask(modes);
|
|
}
|
|
void add_supported_fan_mode(ClimateFanMode mode) { this->supported_fan_modes_.add(mode); }
|
|
void add_supported_custom_fan_mode(const std::string &mode) { this->supported_custom_fan_modes_.push_back(mode); }
|
|
bool supports_fan_mode(ClimateFanMode fan_mode) const { return this->supported_fan_modes_.contains(fan_mode); }
|
|
bool get_supports_fan_modes() const {
|
|
return !this->supported_fan_modes_.empty() || !this->supported_custom_fan_modes_.empty();
|
|
}
|
|
const ClimateFanModeMask &get_supported_fan_modes() const { return this->supported_fan_modes_; }
|
|
|
|
void set_supported_custom_fan_modes(std::vector<std::string> supported_custom_fan_modes) {
|
|
this->supported_custom_fan_modes_ = std::move(supported_custom_fan_modes);
|
|
}
|
|
void set_supported_custom_fan_modes(std::initializer_list<std::string> modes) {
|
|
this->supported_custom_fan_modes_ = modes;
|
|
}
|
|
template<size_t N> void set_supported_custom_fan_modes(const char *const (&modes)[N]) {
|
|
this->supported_custom_fan_modes_.assign(modes, modes + N);
|
|
}
|
|
const std::vector<std::string> &get_supported_custom_fan_modes() const { return this->supported_custom_fan_modes_; }
|
|
bool supports_custom_fan_mode(const std::string &custom_fan_mode) const {
|
|
return vector_contains(this->supported_custom_fan_modes_, custom_fan_mode);
|
|
}
|
|
|
|
void set_supported_presets(ClimatePresetMask presets) { this->supported_presets_ = presets; }
|
|
void set_supported_presets(std::initializer_list<ClimatePreset> presets) {
|
|
this->supported_presets_ = ClimatePresetMask(presets);
|
|
}
|
|
void add_supported_preset(ClimatePreset preset) { this->supported_presets_.add(preset); }
|
|
void add_supported_custom_preset(const std::string &preset) { this->supported_custom_presets_.push_back(preset); }
|
|
bool supports_preset(ClimatePreset preset) const { return this->supported_presets_.contains(preset); }
|
|
bool get_supports_presets() const { return !this->supported_presets_.empty(); }
|
|
const ClimatePresetMask &get_supported_presets() const { return this->supported_presets_; }
|
|
|
|
void set_supported_custom_presets(std::vector<std::string> supported_custom_presets) {
|
|
this->supported_custom_presets_ = std::move(supported_custom_presets);
|
|
}
|
|
void set_supported_custom_presets(std::initializer_list<std::string> presets) {
|
|
this->supported_custom_presets_ = presets;
|
|
}
|
|
template<size_t N> void set_supported_custom_presets(const char *const (&presets)[N]) {
|
|
this->supported_custom_presets_.assign(presets, presets + N);
|
|
}
|
|
const std::vector<std::string> &get_supported_custom_presets() const { return this->supported_custom_presets_; }
|
|
bool supports_custom_preset(const std::string &custom_preset) const {
|
|
return vector_contains(this->supported_custom_presets_, custom_preset);
|
|
}
|
|
|
|
void set_supported_swing_modes(ClimateSwingModeMask modes) { this->supported_swing_modes_ = modes; }
|
|
void set_supported_swing_modes(std::initializer_list<ClimateSwingMode> modes) {
|
|
this->supported_swing_modes_ = ClimateSwingModeMask(modes);
|
|
}
|
|
void add_supported_swing_mode(ClimateSwingMode mode) { this->supported_swing_modes_.add(mode); }
|
|
bool supports_swing_mode(ClimateSwingMode swing_mode) const {
|
|
return this->supported_swing_modes_.contains(swing_mode);
|
|
}
|
|
bool get_supports_swing_modes() const { return !this->supported_swing_modes_.empty(); }
|
|
const ClimateSwingModeMask &get_supported_swing_modes() const { return this->supported_swing_modes_; }
|
|
|
|
float get_visual_min_temperature() const { return this->visual_min_temperature_; }
|
|
void set_visual_min_temperature(float visual_min_temperature) {
|
|
this->visual_min_temperature_ = visual_min_temperature;
|
|
}
|
|
float get_visual_max_temperature() const { return this->visual_max_temperature_; }
|
|
void set_visual_max_temperature(float visual_max_temperature) {
|
|
this->visual_max_temperature_ = visual_max_temperature;
|
|
}
|
|
float get_visual_target_temperature_step() const { return this->visual_target_temperature_step_; }
|
|
float get_visual_current_temperature_step() const { return this->visual_current_temperature_step_; }
|
|
void set_visual_target_temperature_step(float temperature_step) {
|
|
this->visual_target_temperature_step_ = temperature_step;
|
|
}
|
|
void set_visual_current_temperature_step(float temperature_step) {
|
|
this->visual_current_temperature_step_ = temperature_step;
|
|
}
|
|
void set_visual_temperature_step(float temperature_step) {
|
|
this->visual_target_temperature_step_ = temperature_step;
|
|
this->visual_current_temperature_step_ = temperature_step;
|
|
}
|
|
int8_t get_target_temperature_accuracy_decimals() const;
|
|
int8_t get_current_temperature_accuracy_decimals() const;
|
|
|
|
float get_visual_min_humidity() const { return this->visual_min_humidity_; }
|
|
void set_visual_min_humidity(float visual_min_humidity) { this->visual_min_humidity_ = visual_min_humidity; }
|
|
float get_visual_max_humidity() const { return this->visual_max_humidity_; }
|
|
void set_visual_max_humidity(float visual_max_humidity) { this->visual_max_humidity_ = visual_max_humidity; }
|
|
|
|
protected:
|
|
void set_mode_support_(climate::ClimateMode mode, bool supported) {
|
|
if (supported) {
|
|
this->supported_modes_.add(mode);
|
|
} else {
|
|
this->supported_modes_.remove(mode);
|
|
}
|
|
}
|
|
void set_fan_mode_support_(climate::ClimateFanMode mode, bool supported) {
|
|
if (supported) {
|
|
this->supported_fan_modes_.add(mode);
|
|
} else {
|
|
this->supported_fan_modes_.remove(mode);
|
|
}
|
|
}
|
|
void set_swing_mode_support_(climate::ClimateSwingMode mode, bool supported) {
|
|
if (supported) {
|
|
this->supported_swing_modes_.add(mode);
|
|
} else {
|
|
this->supported_swing_modes_.remove(mode);
|
|
}
|
|
}
|
|
|
|
uint32_t feature_flags_{0};
|
|
float visual_min_temperature_{10};
|
|
float visual_max_temperature_{30};
|
|
float visual_target_temperature_step_{0.1};
|
|
float visual_current_temperature_step_{0.1};
|
|
float visual_min_humidity_{30};
|
|
float visual_max_humidity_{99};
|
|
|
|
climate::ClimateModeMask supported_modes_{climate::CLIMATE_MODE_OFF};
|
|
climate::ClimateFanModeMask supported_fan_modes_;
|
|
climate::ClimateSwingModeMask supported_swing_modes_;
|
|
climate::ClimatePresetMask supported_presets_;
|
|
std::vector<std::string> supported_custom_fan_modes_;
|
|
std::vector<std::string> supported_custom_presets_;
|
|
};
|
|
|
|
} // namespace climate
|
|
} // namespace esphome
|