[climate_ir] Store the supported modes in one mask (#19580)

This commit is contained in:
Leonardo Rivera
2026-09-24 12:56:11 +00:00
committed by GitHub
parent 6768cb818b
commit e9aecb5fe8
5 changed files with 59 additions and 30 deletions
+5 -13
View File
@@ -13,17 +13,7 @@ climate::ClimateTraits ClimateIR::traits() {
if (this->humidity_sensor_ != nullptr) {
traits.add_feature_flags(climate::CLIMATE_SUPPORTS_CURRENT_HUMIDITY);
}
traits.set_supported_modes({climate::CLIMATE_MODE_OFF});
if (this->supports_cool_)
traits.add_supported_mode(climate::CLIMATE_MODE_COOL);
if (this->supports_heat_)
traits.add_supported_mode(climate::CLIMATE_MODE_HEAT);
if (this->supports_heat_cool_)
traits.add_supported_mode(climate::CLIMATE_MODE_HEAT_COOL);
if (this->supports_dry_)
traits.add_supported_mode(climate::CLIMATE_MODE_DRY);
if (this->supports_fan_only_)
traits.add_supported_mode(climate::CLIMATE_MODE_FAN_ONLY);
traits.set_supported_modes(this->modes_);
traits.set_visual_min_temperature(this->minimum_temperature_);
traits.set_visual_max_temperature(this->maximum_temperature_);
@@ -98,8 +88,10 @@ void ClimateIR::dump_config() {
" Supports HEAT: %s\n"
" Supports COOL: %s\n"
" Supports HEAT_COOL: %s",
this->minimum_temperature_, this->maximum_temperature_, YESNO(this->supports_heat_),
YESNO(this->supports_cool_), YESNO(this->supports_heat_cool_));
this->minimum_temperature_, this->maximum_temperature_,
YESNO(this->modes_.count(climate::CLIMATE_MODE_HEAT)),
YESNO(this->modes_.count(climate::CLIMATE_MODE_COOL)),
YESNO(this->modes_.count(climate::CLIMATE_MODE_HEAT_COOL)));
}
} // namespace esphome::climate_ir
+21 -11
View File
@@ -30,8 +30,10 @@ class ClimateIR : public Component,
this->minimum_temperature_ = minimum_temperature;
this->maximum_temperature_ = maximum_temperature;
this->temperature_step_ = temperature_step;
this->supports_dry_ = supports_dry;
this->supports_fan_only_ = supports_fan_only;
if (supports_dry)
this->modes_.insert(climate::CLIMATE_MODE_DRY);
if (supports_fan_only)
this->modes_.insert(climate::CLIMATE_MODE_FAN_ONLY);
this->fan_modes_ = fan_modes;
this->swing_modes_ = swing_modes;
this->presets_ = presets;
@@ -39,9 +41,11 @@ class ClimateIR : public Component,
void setup() override;
void dump_config() override;
void set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; }
void set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; }
void set_supports_heat_cool(bool supports_heat_cool) { this->supports_heat_cool_ = supports_heat_cool; }
void set_supports_cool(bool supports_cool) { this->set_mode_supported_(climate::CLIMATE_MODE_COOL, supports_cool); }
void set_supports_heat(bool supports_heat) { this->set_mode_supported_(climate::CLIMATE_MODE_HEAT, supports_heat); }
void set_supports_heat_cool(bool supports_heat_cool) {
this->set_mode_supported_(climate::CLIMATE_MODE_HEAT_COOL, supports_heat_cool);
}
void set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; }
void set_humidity_sensor(sensor::Sensor *sensor) { this->humidity_sensor_ = sensor; }
@@ -59,12 +63,18 @@ class ClimateIR : public Component,
// Dummy implement on_receive so implementation is optional for inheritors
bool on_receive(remote_base::RemoteReceiveData data) override { return false; };
bool supports_cool_{true};
bool supports_heat_{true};
// Default (supports_cool && supports_heat) is resolved during code generation.
bool supports_heat_cool_{true};
bool supports_dry_{false};
bool supports_fan_only_{false};
ESPHOME_ALWAYS_INLINE void set_mode_supported_(climate::ClimateMode mode, bool supported) {
if (supported) {
this->modes_.insert(mode);
} else {
this->modes_.erase(mode);
}
}
// The HEAT_COOL default (supports_cool && supports_heat) is resolved during code generation.
static constexpr climate::ClimateModeMask DEFAULT_MODES{climate::CLIMATE_MODE_OFF, climate::CLIMATE_MODE_COOL,
climate::CLIMATE_MODE_HEAT, climate::CLIMATE_MODE_HEAT_COOL};
climate::ClimateModeMask modes_{DEFAULT_MODES};
climate::ClimateFanModeMask fan_modes_{};
climate::ClimateSwingModeMask swing_modes_{};
climate::ClimatePresetMask presets_{};
+1 -1
View File
@@ -102,7 +102,7 @@ void MitsubishiClimate::transmit_state() {
default:
remote_state[6] = MITSUBISHI_MODE_COOL;
remote_state[8] = MITSUBISHI_MODE_A_COOL;
if (this->supports_heat_) {
if (this->modes_.count(climate::CLIMATE_MODE_HEAT)) {
remote_state[6] = MITSUBISHI_MODE_HEAT;
remote_state[8] = MITSUBISHI_MODE_A_HEAT;
}
+4 -4
View File
@@ -51,10 +51,10 @@ class MitsubishiClimate final : public climate_ir::ClimateIR {
{climate::CLIMATE_PRESET_NONE, climate::CLIMATE_PRESET_ECO, climate::CLIMATE_PRESET_BOOST,
climate::CLIMATE_PRESET_SLEEP}) {}
void set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; }
void set_supports_dry(bool supports_dry) { this->supports_dry_ = supports_dry; }
void set_supports_fan_only(bool supports_fan_only) { this->supports_fan_only_ = supports_fan_only; }
void set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; }
void set_supports_dry(bool supports_dry) { this->set_mode_supported_(climate::CLIMATE_MODE_DRY, supports_dry); }
void set_supports_fan_only(bool supports_fan_only) {
this->set_mode_supported_(climate::CLIMATE_MODE_FAN_ONLY, supports_fan_only);
}
void set_fan_mode(SetFanMode fan_mode) {
this->fan_mode_ = fan_mode;
@@ -5,7 +5,8 @@ namespace esphome::climate_ir::testing {
class TestClimateIR : public ClimateIR {
public:
TestClimateIR() : ClimateIR(16.0f, 30.0f) {}
explicit TestClimateIR(bool supports_dry = false, bool supports_fan_only = false)
: ClimateIR(16.0f, 30.0f, 1.0f, supports_dry, supports_fan_only) {}
using ClimateIR::traits;
@@ -53,4 +54,30 @@ TEST(ClimateIRTest, HeatAndCoolModesFollowTheirOwnFlags) {
EXPECT_TRUE(traits.supports_mode(climate::CLIMATE_MODE_OFF));
}
TEST(ClimateIRTest, DefaultModes) {
TestClimateIR climate;
auto traits = climate.traits();
EXPECT_TRUE(traits.supports_mode(climate::CLIMATE_MODE_OFF));
EXPECT_TRUE(traits.supports_mode(climate::CLIMATE_MODE_COOL));
EXPECT_TRUE(traits.supports_mode(climate::CLIMATE_MODE_HEAT));
EXPECT_TRUE(traits.supports_mode(climate::CLIMATE_MODE_HEAT_COOL));
EXPECT_FALSE(traits.supports_mode(climate::CLIMATE_MODE_DRY));
EXPECT_FALSE(traits.supports_mode(climate::CLIMATE_MODE_FAN_ONLY));
}
TEST(ClimateIRTest, DryAndFanOnlyFromConstructor) {
TestClimateIR climate(true, true);
auto traits = climate.traits();
EXPECT_TRUE(traits.supports_mode(climate::CLIMATE_MODE_DRY));
EXPECT_TRUE(traits.supports_mode(climate::CLIMATE_MODE_FAN_ONLY));
}
TEST(ClimateIRTest, SetterCanTurnAModeBackOn) {
TestClimateIR climate;
climate.set_supports_cool(false);
EXPECT_FALSE(climate.traits().supports_mode(climate::CLIMATE_MODE_COOL));
climate.set_supports_cool(true);
EXPECT_TRUE(climate.traits().supports_mode(climate::CLIMATE_MODE_COOL));
}
} // namespace esphome::climate_ir::testing