9static const char *
const TAG =
"light";
11static const LogString *color_mode_to_human(
ColorMode color_mode) {
13 return LOG_STR(
"Unknown");
15 return LOG_STR(
"White");
17 return LOG_STR(
"Color temperature");
19 return LOG_STR(
"Cold/warm white");
21 return LOG_STR(
"RGB");
23 return LOG_STR(
"RGBW");
25 return LOG_STR(
"RGB + cold/warm white");
27 return LOG_STR(
"RGB + color temperature");
36 ESP_LOGD(TAG,
"'%s' Setting:", name);
41 ESP_LOGD(TAG,
" Color mode: %s", LOG_STR_ARG(color_mode_to_human(v.
get_color_mode())));
47 ESP_LOGD(TAG,
" State: %s", ONOFF(v.
is_on()));
57 if (this->
red_.
has_value() || this->green_.has_value() || this->blue_.has_value()) {
58 ESP_LOGD(TAG,
" Red: %.0f%%, Green: %.0f%%, Blue: %.0f%%", v.
get_red() * 100.0f, v.
get_green() * 100.0f,
63 ESP_LOGD(TAG,
" White: %.0f%%", v.
get_white() * 100.0f);
70 ESP_LOGD(TAG,
" Cold white: %.0f%%, warm white: %.0f%%", v.
get_cold_white() * 100.0f,
78 ESP_LOGD(TAG,
" Flash length: %.1fs", *this->
flash_length_ / 1e3f);
91 ESP_LOGD(TAG,
" Effect: 'None'");
101 const char *effect_s;
109 ESP_LOGD(TAG,
" Effect: '%s'", effect_s);
139 ESP_LOGW(TAG,
"'%s' - This light does not support color mode %s!", name,
155 ESP_LOGW(TAG,
"'%s' - This light does not support setting brightness!", name);
162 ESP_LOGW(TAG,
"'%s' - This light does not support transitions!", name);
168 ESP_LOGW(TAG,
"'%s' - This color mode does not support setting RGB brightness!", name);
173 if ((this->
red_.
has_value() && *this->red_ > 0.0f) || (this->green_.has_value() && *this->green_ > 0.0f) ||
174 (this->blue_.has_value() && *this->blue_ > 0.0f)) {
176 ESP_LOGW(TAG,
"'%s' - This color mode does not support setting RGB color!", name);
186 ESP_LOGW(TAG,
"'%s' - This color mode does not support setting white value!", name);
193 ESP_LOGW(TAG,
"'%s' - This color mode does not support setting color temperature!", name);
199 (this->warm_white_.has_value() && *this->warm_white_ > 0.0f)) {
201 ESP_LOGW(TAG,
"'%s' - This color mode does not support setting cold/warm white value!", name);
207#define VALIDATE_RANGE_(name_, upper_name, min, max) \
208 if (name_##_.has_value()) { \
209 auto val = *name_##_; \
210 if (val < (min) || val > (max)) { \
211 ESP_LOGW(TAG, "'%s' - %s value %.2f is out of range [%.1f - %.1f]!", name, LOG_STR_LITERAL(upper_name), val, \
213 name_##_ = clamp(val, (min), (max)); \
216#define VALIDATE_RANGE(name, upper_name) VALIDATE_RANGE_(name, upper_name, 0.0f, 1.0f)
219 VALIDATE_RANGE(brightness,
"Brightness")
220 VALIDATE_RANGE(color_brightness,
"Color brightness")
221 VALIDATE_RANGE(red,
"Red")
222 VALIDATE_RANGE(green,
"Green")
223 VALIDATE_RANGE(blue,
"Blue")
224 VALIDATE_RANGE(white,
"White")
225 VALIDATE_RANGE(cold_white,
"Cold white")
226 VALIDATE_RANGE(warm_white,
"Warm white")
227 VALIDATE_RANGE_(color_temperature,
"Color temperature", traits.get_min_mireds(), traits.get_max_mireds())
239 if (this->
red_.
has_value() || this->green_.has_value() || this->blue_.has_value()) {
249 v.set_state(*this->
state_);
255 v.set_red(*this->
red_);
257 v.set_green(*this->
green_);
259 v.set_blue(*this->
blue_);
261 v.set_white(*this->
white_);
273 ESP_LOGW(TAG,
"'%s' - Flash length must be greater than zero!", name);
287 ESP_LOGW(TAG,
"'%s' - Invalid effect index %" PRIu32
"!", name, *this->
effect_);
292 ESP_LOGW(TAG,
"'%s' - Effect cannot be used together with transition/flash!", name);
298 ESP_LOGW(TAG,
"'%s' - Flash cannot be used together with transition!", name);
303 supports_transition) {
314 ESP_LOGW(TAG,
"'%s' - Light does not support transitions!", name);
323 ESP_LOGW(TAG,
"'%s' - Cannot start an effect when turning off!", name);
346 if (((this->
white_.
has_value() && *this->white_ > 0.0f) || this->color_temperature_.has_value()) &&
350 traits.get_min_mireds() > 0.0f && traits.get_max_mireds() > 0.0f) {
351 ESP_LOGD(TAG,
"'%s' - Setting cold/warm white channels using white/color temperature values.",
355 const float ww_fraction =
356 (color_temp - traits.get_min_mireds()) / (traits.get_max_mireds() - traits.get_min_mireds());
357 const float cw_fraction = 1.0f - ww_fraction;
358 const float max_cw_ww = std::max(ww_fraction, cw_fraction);
369 int supported_count = supported_modes.size();
372 if (supported_count == 0)
376 if (supported_count == 1)
377 return *supported_modes.begin();
390 if (suitable_modes.count(current_mode) > 0) {
391 ESP_LOGI(TAG,
"'%s' - Keeping current color mode %s for call without color mode.",
397 for (
auto mode : suitable_modes) {
398 if (supported_modes.count(
mode) == 0)
401 ESP_LOGI(TAG,
"'%s' - Using color mode %s for call without color mode.", this->
parent_->
get_name().
c_str(),
402 LOG_STR_ARG(color_mode_to_human(
mode)));
408 auto color_mode = current_mode !=
ColorMode::UNKNOWN ? current_mode : *supported_modes.begin();
409 ESP_LOGW(TAG,
"'%s' - No color mode suitable for this call supported, defaulting to %s!",
421#define KEY(white, ct, cwww, rgb) ((white) << 0 | (ct) << 1 | (cwww) << 2 | (rgb) << 3)
422#define ENTRY(white, ct, cwww, rgb, ...) \
423 std::make_tuple<uint8_t, std::set<ColorMode>>(KEY(white, ct, cwww, rgb), __VA_ARGS__)
426 std::array<std::tuple<uint8_t, std::set<ColorMode>>, 10> lookup_table{
427 ENTRY(
true,
false,
false,
false,
430 ENTRY(
false,
true,
false,
false,
433 ENTRY(
true,
true,
false,
false,
436 ENTRY(
false,
false,
false,
false,
439 ENTRY(
true,
false,
false,
true,
444 ENTRY(
false,
false,
false,
true,
448 auto key = KEY(has_white, has_ct, has_cwww, has_rgb);
449 for (
auto &item : lookup_table) {
450 if (std::get<0>(item) == key)
451 return std::get<1>(item);
459 if (strcasecmp(effect.c_str(),
"none") == 0) {
468 if (strcasecmp(effect.c_str(), e->
get_name().c_str()) == 0) {
684 this->
set_rgb(red, green, blue);
BedjetMode mode
BedJet operating mode.
const StringRef & get_name() const
constexpr const char * c_str() const
This class represents a requested change in a light state.
LightCall & set_color_mode_if_supported(ColorMode color_mode)
Set the color mode of the light, if this mode is supported.
optional< float > brightness_
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.
ColorMode compute_color_mode_()
optional< ColorMode > color_mode_
LightCall & set_color_brightness(optional< float > brightness)
Set the color brightness of the light from 0.0 (no color) to 1.0 (fully on)
optional< float > color_brightness_
LightCall & set_rgb(float red, float green, float blue)
Set the RGB color of the light by RGB values.
optional< uint32_t > flash_length_
LightCall & set_transition_length_if_supported(uint32_t transition_length)
Set the transition length property if the light supports transitions.
LightCall & set_red_if_supported(float red)
Set the red property if the light supports RGB.
optional< float > cold_white_
LightCall & set_effect(optional< std::string > effect)
Set the effect of the light by its name.
std::set< ColorMode > get_suitable_color_modes_()
Get potential color modes for this light call.
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.
optional< float > warm_white_
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.
LightCall & set_blue(optional< float > blue)
Set the blue RGB value of the light from 0.0 to 1.0.
LightCall & set_flash_length(optional< uint32_t > flash_length)
Start and set the flash length of this call in milliseconds.
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.
optional< float > color_temperature_
optional< uint32_t > effect_
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.
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.
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.
void transform_parameters_()
Some color modes also can be set using non-native parameters, transform those calls.
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.
optional< uint32_t > transition_length_
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.
const std::string & get_name()
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 get_gamma_correct() const
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.
std::vector< LightEffect * > effects_
List of effects for this light.
CallbackManager< void()> target_state_reached_callback_
Callback to call when the state of current_values and remote_values are equal This should be called o...
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.
bool supports_color_mode(ColorMode color_mode) const
const std::set< ColorMode > & get_supported_color_modes() const
value_type value_or(U const &v) const
value_type const & value() const
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.
Providing packet encoding functions for exchanging data with a remote host.
float gamma_uncorrect(float value, float gamma)
Reverts gamma correction of gamma to value.
constexpr const T & clamp(const T &v, const T &lo, const T &hi, Compare comp)