1
0
mirror of https://github.com/esphome/esphome.git synced 2025-10-24 20:53:48 +01:00
This commit is contained in:
J. Nick Koston
2025-10-18 13:46:49 -10:00
parent 8545b5231b
commit a249c9c282
2 changed files with 54 additions and 28 deletions

View File

@@ -213,6 +213,13 @@ class ColorModeMask {
constexpr void add(ColorMode mode) { this->mask_ |= (1 << mode_to_bit(mode)); }
/// Add multiple modes at once using initializer list
constexpr void add(std::initializer_list<ColorMode> modes) {
for (auto mode : modes) {
this->add(mode);
}
}
constexpr bool contains(ColorMode mode) const { return (this->mask_ & (1 << mode_to_bit(mode))) != 0; }
constexpr size_t size() const {
@@ -300,23 +307,6 @@ class ColorModeMask {
return (this->mask_ & CAPABILITY_BITMASKS[index]) != 0;
}
/// Build a bitmask of modes that match the given capability requirements
/// @param require_caps Capabilities that must be present in the mode
/// @return Raw bitmask value
static constexpr color_mode_bitmask_t build_mask_matching(uint8_t require_caps) {
color_mode_bitmask_t mask = 0;
// Check each mode to see if it matches the requirements
// Skip UNKNOWN (bit 0), iterate through actual color modes (bits 1-9)
for (int bit = 1; bit < COLOR_MODE_COUNT; ++bit) {
uint8_t mode_val = static_cast<uint8_t>(bit_to_mode(bit));
// Mode matches if it has all required caps
if ((mode_val & require_caps) == require_caps) {
mask |= (1 << bit);
}
}
return mask;
}
private:
// Using uint16_t instead of uint32_t for more efficient iteration (fewer bits to scan).
// Currently only 10 ColorMode values exist, so 16 bits is sufficient.

View File

@@ -458,18 +458,54 @@ color_mode_bitmask_t LightCall::get_suitable_color_modes_mask_() {
bool has_rgb = (this->has_color_brightness() && this->color_brightness_ > 0.0f) ||
(this->has_red() || this->has_green() || this->has_blue());
// Build required capabilities mask
uint8_t require_caps = static_cast<uint8_t>(ColorCapability::ON_OFF | ColorCapability::BRIGHTNESS);
if (has_rgb)
require_caps |= static_cast<uint8_t>(ColorCapability::RGB);
if (has_white)
require_caps |= static_cast<uint8_t>(ColorCapability::WHITE);
if (has_ct)
require_caps |= static_cast<uint8_t>(ColorCapability::COLOR_TEMPERATURE);
if (has_cwww)
require_caps |= static_cast<uint8_t>(ColorCapability::COLD_WARM_WHITE);
// Build key from flags: [rgb][cwww][ct][white]
#define KEY(white, ct, cwww, rgb) ((white) << 0 | (ct) << 1 | (cwww) << 2 | (rgb) << 3)
return ColorModeMask::build_mask_matching(require_caps);
uint8_t key = KEY(has_white, has_ct, has_cwww, has_rgb);
// Build bitmask from suitable ColorModes
ColorModeMask suitable;
switch (key) {
case KEY(true, false, false, false): // white only
suitable.add({ColorMode::WHITE, ColorMode::RGB_WHITE, ColorMode::RGB_COLOR_TEMPERATURE,
ColorMode::COLD_WARM_WHITE, ColorMode::RGB_COLD_WARM_WHITE});
break;
case KEY(false, true, false, false): // ct only
suitable.add({ColorMode::COLOR_TEMPERATURE, ColorMode::RGB_COLOR_TEMPERATURE, ColorMode::COLD_WARM_WHITE,
ColorMode::RGB_COLD_WARM_WHITE});
break;
case KEY(true, true, false, false): // white + ct
suitable.add({ColorMode::COLD_WARM_WHITE, ColorMode::RGB_COLOR_TEMPERATURE, ColorMode::RGB_COLD_WARM_WHITE});
break;
case KEY(false, false, true, false): // cwww only
suitable.add({ColorMode::COLD_WARM_WHITE, ColorMode::RGB_COLD_WARM_WHITE});
break;
case KEY(false, false, false, false): // none
suitable.add({ColorMode::RGB_WHITE, ColorMode::RGB_COLOR_TEMPERATURE, ColorMode::RGB_COLD_WARM_WHITE,
ColorMode::RGB, ColorMode::WHITE, ColorMode::COLOR_TEMPERATURE, ColorMode::COLD_WARM_WHITE});
break;
case KEY(true, false, false, true): // rgb + white
suitable.add({ColorMode::RGB_WHITE, ColorMode::RGB_COLOR_TEMPERATURE, ColorMode::RGB_COLD_WARM_WHITE});
break;
case KEY(false, true, false, true): // rgb + ct
case KEY(true, true, false, true): // rgb + white + ct
suitable.add({ColorMode::RGB_COLOR_TEMPERATURE, ColorMode::RGB_COLD_WARM_WHITE});
break;
case KEY(false, false, true, true): // rgb + cwww
suitable.add(ColorMode::RGB_COLD_WARM_WHITE);
break;
case KEY(false, false, false, true): // rgb only
suitable.add(
{ColorMode::RGB, ColorMode::RGB_WHITE, ColorMode::RGB_COLOR_TEMPERATURE, ColorMode::RGB_COLD_WARM_WHITE});
break;
default:
break; // conflicting flags - return empty mask
}
#undef KEY
return suitable.get_mask();
}
LightCall &LightCall::set_effect(const std::string &effect) {