11static const char *
const TAG =
"light";
15static void log_value_out_of_range(
const char *name,
float value,
const LogString *param_name,
float min,
float max) {
16 ESP_LOGW(TAG,
"'%s': %s value %.2f is out of range [%.1f - %.1f]", name, LOG_STR_ARG(param_name), value, min, max);
19#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_WARN
20static void log_feature_not_supported(
const char *name,
const LogString *feature) {
21 ESP_LOGW(TAG,
"'%s': %s not supported", name, LOG_STR_ARG(feature));
24static void log_color_mode_not_supported(
const char *name,
const LogString *feature) {
25 ESP_LOGW(TAG,
"'%s': color mode does not support setting %s", name, LOG_STR_ARG(feature));
28static void log_invalid_parameter(
const char *name,
const LogString *
message) {
29 ESP_LOGW(TAG,
"'%s': %s", name, LOG_STR_ARG(
message));
32#define log_feature_not_supported(name, feature)
33#define log_color_mode_not_supported(name, feature)
34#define log_invalid_parameter(name, message)
38#define IMPLEMENT_LIGHT_CALL_SETTER(name, type, flag) \
39 LightCall &LightCall::set_##name(optional<type>(name)) { \
40 if ((name).has_value()) { \
41 this->name##_ = (name).value(); \
43 this->set_flag_(flag, (name).has_value()); \
46 LightCall &LightCall::set_##name(type name) { \
47 this->name##_ = name; \
48 this->set_flag_(flag); \
54PROGMEM_STRING_TABLE(ColorModeHumanStrings,
"Unknown",
"On/Off",
"Brightness",
"White",
"Color temperature",
55 "Cold/warm white",
"RGB",
"RGBW",
"RGB + color temperature",
"RGB + cold/warm white");
60 "Cold white",
"Warm white",
"Color temperature");
61static constexpr uint8_t VALIDATE_CT_INDEX = 8;
63static const LogString *color_mode_to_human(
ColorMode color_mode) {
68#if ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE
69static void log_percent(
const LogString *param,
float value) {
70 ESP_LOGV(TAG,
" %s: %.0f%%", LOG_STR_ARG(param), value * 100.0f);
73#define log_percent(param, value)
82 ESP_LOGV(TAG,
"'%s' Setting:", name);
87 if (target_color_mode != current_color_mode) {
88 ESP_LOGV(TAG,
" Color mode: %s", LOG_STR_ARG(color_mode_to_human(v.
get_color_mode())));
94 if (target_state != current_state) {
95 ESP_LOGV(TAG,
" State: %s", ONOFF(v.
is_on()));
106 ESP_LOGV(TAG,
" Red: %.0f%%, Green: %.0f%%, Blue: %.0f%%", v.
get_red() * 100.0f, v.
get_green() * 100.0f,
111 log_percent(LOG_STR(
"White"), v.
get_white());
118 ESP_LOGV(TAG,
" Cold white: %.0f%%, warm white: %.0f%%", v.
get_cold_white() * 100.0f,
126 ESP_LOGV(TAG,
" Flash length: %.1fs", this->
flash_length_ / 1e3f);
139 ESP_LOGV(TAG,
" Effect: 'None'");
156 ESP_LOGV(TAG,
" Effect: '%.*s'", (
int) effect_s.
size(), effect_s.
c_str());
171 listener->on_light_target_state_reached();
184 if (use_color_mode_log) {
185 log_color_mode_not_supported(name, feature);
187 log_feature_not_supported(name, feature);
197 if (this->
has_color_mode() && !traits.supports_color_mode(this->color_mode_)) {
198 ESP_LOGW(TAG,
"'%s' does not support color mode %s", name, LOG_STR_ARG(color_mode_to_human(this->
color_mode_)));
222 this->brightness_ = 1.0f;
233 this->color_brightness_ = 1.0f;
249 if (((this->
has_red() && this->red_ > 0.0f) || (this->
has_green() && this->green_ > 0.0f) ||
250 (this->
has_blue() && this->blue_ > 0.0f)) &&
252 log_color_mode_not_supported(name, LOG_STR(
"RGB color"));
259 if (this->
has_white() && this->white_ > 0.0f &&
271 log_color_mode_not_supported(name, LOG_STR(
"cold/warm white value"));
281 v.set_state(this->
state_);
287 "FieldFlags bits 0-7 must match unit_fields_ indices");
292 while (active != 0) {
293 unsigned bit = __builtin_ctz(active);
294 active &= active - 1;
295 float &value = this->unit_fields_[bit];
297 log_value_out_of_range(name, value, ValidateFieldNames::get_log_str(bit, 0), 0.0f, 1.0f);
300 v.unit_fields_[bit] = value;
305 const float ct_min = traits.get_min_mireds();
306 const float ct_max = traits.get_max_mireds();
308 log_value_out_of_range(name, this->
color_temperature_, ValidateFieldNames::get_log_str(VALIDATE_CT_INDEX, 0),
319 log_invalid_parameter(name, LOG_STR(
"flash length must be >0"));
333 ESP_LOGW(TAG,
"'%s': invalid effect index %" PRIu32, name, this->
effect_);
338 log_invalid_parameter(name, LOG_STR(
"effect cannot be used with transition/flash"));
344 log_invalid_parameter(name, LOG_STR(
"flash cannot be used with transition"));
349 supports_transition) {
369 log_invalid_parameter(name, LOG_STR(
"cannot start effect when turning off"));
400 min_mireds > 0.0f && max_mireds > 0.0f) {
401 ESP_LOGV(TAG,
"'%s': setting cold/warm white channels using white/color temperature values",
408 const float range = max_mireds - min_mireds;
409 const float ww_fraction = (color_temp - min_mireds) /
range;
410 const float cw_fraction = 1.0f - ww_fraction;
411 const float max_cw_ww = std::max(ww_fraction, cw_fraction);
418 this->brightness_ = this->white_;
425 int supported_count = supported_modes.
size();
428 if (supported_count == 0)
432 if (supported_count == 1)
433 return *supported_modes.begin();
448 ESP_LOGV(TAG,
"'%s': color mode not specified; retaining %s", this->
parent_->
get_name().
c_str(),
449 LOG_STR_ARG(color_mode_to_human(current_mode)));
454 if (intersection != 0) {
457 LOG_STR_ARG(color_mode_to_human(
mode)));
463 auto color_mode = current_mode !=
ColorMode::UNKNOWN ? current_mode : *supported_modes.begin();
464 ESP_LOGW(TAG,
"'%s': no suitable color mode supported; defaulting to %s", this->
parent_->
get_name().
c_str(),
465 LOG_STR_ARG(color_mode_to_human(color_mode)));
474static constexpr uint8_t SUITABLE_COLOR_MODES[] PROGMEM = {
523 uint8_t key =
has_white | (has_ct << 1) | (has_cwww << 2) | (has_rgb << 3);
528 if (
len == 4 && strncasecmp(effect,
"none", 4) == 0) {
543 ESP_LOGW(TAG,
"'%s': no such effect '%.*s'", this->
parent_->
get_name().
c_str(), (
int) len, effect);
634 if (effect.has_value())
644 if (effect_number.has_value()) {
645 this->
effect_ = effect_number.value();
665 this->
set_rgb(red, green, blue);
BedjetMode mode
BedJet operating mode.
const StringRef & get_name() const
static constexpr ColorMode first_value_from_mask(bitmask_t mask)
constexpr bitmask_t get_mask() const
Get the raw bitmask value for optimized operations.
constexpr size_t size() const
Count the number of values in the set.
static constexpr bool mask_contains(bitmask_t mask, ColorMode value)
StringRef is a reference to a string owned by something else.
constexpr const char * c_str() const
constexpr size_type size() const
static constexpr StringRef from_lit(const CharT(&s)[N])
This class represents a requested change in a light state.
bool has_color_mode() const
bool has_color_temperature() const
LightCall & set_color_mode_if_supported(ColorMode color_mode)
Set the color mode of the light, if this mode is supported.
LightCall & set_color_temperature(optional< float > color_temperature)
Set the color temperature of the light in mireds for CWWW or RGBWW lights.
LightCall & set_publish(bool publish)
Set whether this light call should trigger a publish state.
void log_and_clear_unsupported_(FieldFlags flag, const LogString *feature, bool use_color_mode_log)
LightCall & set_color_brightness(optional< float > brightness)
Set the color brightness of the light from 0.0 (no color) to 1.0 (fully on)
bool has_warm_white() const
void set_flag_(FieldFlags flag, bool value=true) ESPHOME_ALWAYS_INLINE
bool has_brightness() const
LightCall & set_rgb(float red, float green, float blue)
Set the RGB color of the light by RGB values.
bool has_cold_white() const
void transform_parameters_(const LightTraits &traits)
Some color modes also can be set using non-native parameters, transform those calls.
LightCall & set_transition_length_if_supported(uint32_t transition_length)
Set the transition length property if the light supports transitions.
bool has_color_brightness() const
LightCall & set_red_if_supported(float red)
Set the red property if the light supports RGB.
LightCall & set_effect(optional< std::string > effect)
Set the effect of the light by its name.
LightCall & set_color_brightness_if_supported(float brightness)
Set the color brightness property if the light supports RGBW.
LightCall & set_white(optional< float > white)
Set the white value value of the light from 0.0 to 1.0 for RGBW[W] lights.
LightCall & set_green(optional< float > green)
Set the green RGB value of the light from 0.0 to 1.0.
LightCall & set_green_if_supported(float green)
Set the green property if the light supports RGB.
LightCall & set_warm_white(optional< float > warm_white)
Set the warm white value of the light from 0.0 to 1.0.
LightCall & set_rgbw(float red, float green, float blue, float white)
Set the RGBW color of the light by RGB values.
LightCall & set_save(bool save)
Set whether this light call should trigger a save state to recover them at startup....
LightCall & set_color_temperature_if_supported(float color_temperature)
Set the color_temperature property if the light supports color temperature.
void clear_flag_(FieldFlags flag) ESPHOME_ALWAYS_INLINE
LightCall & set_blue(optional< float > blue)
Set the blue RGB value of the light from 0.0 to 1.0.
LightCall & set_cold_white(optional< float > cold_white)
Set the cold white value of the light from 0.0 to 1.0.
LightCall & set_red(optional< float > red)
Set the red RGB value of the light from 0.0 to 1.0.
ColorMode get_active_color_mode_()
Get the currently targeted, or active if none set, color mode.
LightCall & set_white_if_supported(float white)
Set the white property if the light supports RGB.
LightCall & set_cold_white_if_supported(float cold_white)
Set the cold white property if the light supports cold white output.
LightCall & set_warm_white_if_supported(float warm_white)
Set the warm white property if the light supports cold white output.
ColorMode compute_color_mode_(const LightTraits &traits)
@ FLAG_HAS_COLOR_TEMPERATURE
@ FLAG_HAS_COLOR_BRIGHTNESS
static constexpr uint16_t CLAMP_FLAGS_MASK
LightCall & set_brightness_if_supported(float brightness)
Set the brightness property if the light supports brightness.
LightColorValues validate_()
Validate all properties and return the target light color values.
uint32_t transition_length_
LightCall & set_brightness(optional< float > brightness)
Set the target brightness of the light from 0.0 (fully off) to 1.0 (fully on)
LightCall & set_blue_if_supported(float blue)
Set the blue property if the light supports RGB.
LightCall & from_light_color_values(const LightColorValues &values)
LightCall & set_state(optional< bool > state)
Set the binary ON/OFF state of the light.
LightCall & set_color_mode(optional< ColorMode > color_mode)
Set the color mode of the light.
color_mode_bitmask_t get_suitable_color_modes_mask_()
Get potential color modes bitmask for this light call.
LightCall & set_transition_length(optional< uint32_t > transition_length)
Set the transition length of this call in milliseconds.
This class represents the color state for a light object.
void set_color_mode(ColorMode color_mode)
Set the color mode of these light color values.
float get_brightness() const
Get the brightness property of these light color values. In range 0.0 to 1.0.
float get_blue() const
Get the blue property of these light color values. In range 0.0 to 1.0.
float get_white() const
Get the white property of these light color values. In range 0.0 to 1.0.
float get_color_temperature() const
Get the color temperature property of these light color values in mired.
float get_cold_white() const
Get the cold white property of these light color values. In range 0.0 to 1.0.
bool is_on() const
Get the binary true/false state of these light color values.
float get_green() const
Get the green property of these light color values. In range 0.0 to 1.0.
float get_warm_white() const
Get the warm white property of these light color values. In range 0.0 to 1.0.
ColorMode get_color_mode() const
Get the color mode of these light color values.
float get_red() const
Get the red property of these light color values. In range 0.0 to 1.0.
float get_color_brightness() const
Get the color brightness property of these light color values. In range 0.0 to 1.0.
FixedVector< LightEffect * > effects_
List of effects for this light.
void start_effect_(uint32_t effect_index)
Internal method to start an effect with the given index.
void stop_effect_()
Internal method to stop the current effect (if one is active).
LightColorValues remote_values
The remote color values reported to the frontend.
void save_remote_values_()
Internal method to save the current remote_values to the preferences.
void set_immediately_(const LightColorValues &target, bool set_remote_values)
Internal method to set the color values to target immediately (with no transition).
float gamma_uncorrect_lut(float value) const
Reverse gamma correction by binary-searching the forward LUT.
void publish_state()
Publish the currently active state to the frontend.
uint32_t active_effect_index_
Value for storing the index of the currently active effect. 0 if no effect is active.
void start_flash_(const LightColorValues &target, uint32_t length, bool set_remote_values)
Internal method to start a flash for the specified amount of time.
void start_transition_(const LightColorValues &target, uint32_t length, bool set_remote_values)
Internal method to start a transition to the target color with the given length.
uint32_t default_transition_length_
Default transition length for all transitions in ms.
std::unique_ptr< std::vector< LightTargetStateReachedListener * > > target_state_reached_listeners_
Listeners for target state reached.
This class is used to represent the capabilities of a light.
float get_max_mireds() const
bool supports_color_mode(ColorMode color_mode) const
ColorModeMask get_supported_color_modes() const
float get_min_mireds() const
IMPLEMENT_LIGHT_CALL_SETTER(state, bool, FLAG_HAS_STATE) IMPLEMENT_LIGHT_CALL_SETTER(transition_length
float clamp_unit_float(float x)
PROGMEM_STRING_TABLE(ColorModeHumanStrings, "Unknown", "On/Off", "Brightness", "White", "Color temperature", "Cold/warm white", "RGB", "RGBW", "RGB + color temperature", "RGB + cold/warm white")
FiniteSetMask< ColorMode, ColorModeBitPolicy > ColorModeMask
bool float_out_of_unit_range(float x)
uint16_t color_mode_bitmask_t
ColorMode
Color modes are a combination of color capabilities that can be used at the same time.
@ RGB_COLD_WARM_WHITE
RGB color output, and separate cold and warm white outputs.
@ UNKNOWN
No color mode configured (cannot be a supported mode, only active when light is off).
@ RGB_WHITE
RGB color output and a separate white output.
@ RGB_COLOR_TEMPERATURE
RGB color output and a separate white output with controllable color temperature.
@ COLOR_TEMPERATURE
Controllable color temperature output.
@ WHITE
White output only (use only if the light also has another color mode such as RGB).
@ COLD_WARM_WHITE
Cold and warm white output with individually controllable brightness.
@ BRIGHTNESS
Master brightness of the light can be controlled.
@ RGB
Color can be controlled using RGB format (includes a brightness control for the color).
@ COLOR_TEMPERATURE
Color temperature can be controlled.
@ WHITE
Brightness of white channel can be controlled separately from other channels.
@ COLD_WARM_WHITE
Brightness of cold and warm white output can be controlled.
bool str_equals_case_insensitive(const std::string &a, const std::string &b)
Compare strings for equality in case-insensitive manner.
uint8_t progmem_read_byte(const uint8_t *addr)
static constexpr unsigned to_bit(ColorMode mode)