ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
light_state.cpp
Go to the documentation of this file.
1#include "light_state.h"
4#ifdef USE_LIGHT_TRANSITION_PUBLISH_INTERVAL
6#endif
8#include "esphome/core/log.h"
9#include "light_output.h"
10#include "transformers.h"
11
12namespace esphome::light {
13
14ESPHOME_LOG_TAG(TAG, "light");
15
16// Colour modes are bitmasks of capabilities. A mode the light doesn't support may be a bare set of
17// required capabilities (see restore_state.py's colour mode inference): use the first supported
18// mode that provides all of them, or leave it unchanged if there is none.
19static ColorMode resolve_color_mode(const LightTraits &traits, ColorMode requested) {
20 if (requested == ColorMode::UNKNOWN || traits.supports_color_mode(requested))
21 return requested;
22 auto wanted = static_cast<uint8_t>(requested);
23 for (ColorMode mode : traits.get_supported_color_modes()) {
24 if ((static_cast<uint8_t>(mode) & wanted) == wanted)
25 return mode;
26 }
27 return requested;
28}
29
30LightState::LightState(LightOutput *output) : output_(output) {}
31
37
39 this->output_->setup_state(this);
40 for (auto *effect : this->effects_) {
41 effect->init_internal(this);
42 }
43
44 // Start with loop disabled if idle - respects any effects/transitions set up during initialization
46
47 // When supported color temperature range is known, initialize color temperature setting within bounds.
48 auto traits = this->get_traits();
49 float min_mireds = traits.get_min_mireds();
50 if (min_mireds > 0) {
51 this->remote_values.set_color_temperature(min_mireds);
52 this->current_values.set_color_temperature(min_mireds);
53 }
54
55 auto call = this->make_call();
56 LightStateRTCState recovered{};
57 bool restored = false;
58 if (this->save_enabled_) {
60 restored = this->rtc_.load(&recovered);
61 }
62 if (this->state_callback_) {
63 this->state_callback_(recovered, restored);
64 this->state_callback_ = nullptr; // One-shot — no longer needed
65 }
66
67 // A light coming up on boot must never end up on-but-invisible: if the resolved restore
68 // state is on but its brightness is zero (e.g. a stale/persisted value from before a
69 // forced-on restore mode, or an inverted restore flipping a dim-to-0 off state to on),
70 // reset it to full brightness.
71 if (recovered.state && recovered.brightness == 0.0f) {
72 recovered.brightness = 1.0f;
73 }
74
75 call.set_color_mode_if_supported(resolve_color_mode(traits, recovered.color_mode));
76 call.set_state(recovered.state);
77 call.set_brightness_if_supported(recovered.brightness);
78 call.set_color_brightness_if_supported(recovered.color_brightness);
79 call.set_red_if_supported(recovered.red);
80 call.set_green_if_supported(recovered.green);
81 call.set_blue_if_supported(recovered.blue);
82 call.set_white_if_supported(recovered.white);
83 call.set_color_temperature_if_supported(recovered.color_temp);
84 call.set_cold_white_if_supported(recovered.cold_white);
85 call.set_warm_white_if_supported(recovered.warm_white);
86 if (recovered.state && recovered.effect != 0) {
87 call.set_effect(recovered.effect);
88 } else {
89#ifdef USE_LIGHT_RESUME_EFFECT
90 // An off light cannot start its effect now; keep it for the first turn-on instead
91 this->previous_effect_index_ = recovered.effect;
92#endif // USE_LIGHT_RESUME_EFFECT
93 call.set_transition_length_if_supported(0);
94 }
95 call.perform();
96}
98 ESP_LOGCONFIG(TAG, "Light '%s'", LOG_STR_ARG(this->get_log_name()));
99 auto traits = this->get_traits();
100 if (traits.supports_color_capability(ColorCapability::BRIGHTNESS)) {
101#ifdef USE_LIGHT_GAMMA_LUT
102 // Read the stored gamma * 100 directly so dump_config does not pull in get_gamma_correct()
103 const unsigned gamma_x100 =
104 this->gamma_table_ != nullptr ? progmem_read_uint16(&this->gamma_table_->gamma_x100) : 0;
105#else
106 const unsigned gamma_x100 = 0;
107#endif
108 ESP_LOGCONFIG(TAG,
109 " Default Transition Length: %.1fs\n"
110 " Gamma Correct: %u.%02u",
111 this->default_transition_length_ / 1e3f, gamma_x100 / 100, gamma_x100 % 100);
112#ifdef USE_LIGHT_TRANSITION_PUBLISH_INTERVAL
113 // The define is build wide; only lights that set the option have an interval
114 if (this->transition_state_publish_interval_ != 0) {
115 ESP_LOGCONFIG(TAG, " Transition State Publish Interval: %" PRIu32 "ms",
117 }
118#endif
119 }
120 if (traits.supports_color_capability(ColorCapability::COLOR_TEMPERATURE)) {
121 ESP_LOGCONFIG(TAG,
122 " Min Mireds: %.1f\n"
123 " Max Mireds: %.1f",
124 traits.get_min_mireds(), traits.get_max_mireds());
125 }
126}
131
133 // Apply effect (if any)
134 auto *effect = this->get_active_effect_();
135 if (effect != nullptr) {
136 effect->apply();
137 }
138
139 // Apply transformer (if any)
140 if (this->transformer_ != nullptr) {
141 auto values = this->transformer_->apply();
142 this->is_transformer_active_ = true;
143 if (values.has_value()) {
144 this->current_values = *values;
145 this->output_->update_state(this);
146 this->next_write_ = true;
147 }
148
149 const bool finished = this->transformer_->is_finished();
150#ifdef USE_LIGHT_TRANSITION_PUBLISH_INTERVAL
151 if (this->transition_publish_enabled_ && !finished) {
154 this->publish_state();
156 }
157 }
158#endif
159
160 if (finished) {
161 // if the transition has written directly to the output, current_values is outdated, so update it
162 this->current_values = this->transformer_->get_target_values();
163 this->transformer_->stop();
164 this->is_transformer_active_ = false;
165 this->transformer_ = nullptr;
166#ifdef USE_LIGHT_TRANSITION_PUBLISH_INTERVAL
167 if (this->transition_publish_enabled_) {
168 // Report the end state from remote_values; a flash's stop() left publishing to us
169 this->transition_publish_enabled_ = false;
170 this->publish_state();
171 }
172#endif
174 for (auto *listener : *this->target_state_reached_listeners_) {
175 listener->on_light_target_state_reached();
176 }
177 }
178
179 // Disable loop if idle (no transformer and no effect)
180 this->disable_loop_if_idle_();
181 }
182 }
183}
184
186 if (this->next_write_) {
187 this->next_write_ = false;
188 this->output_->write_state(this);
189 // Disable loop if idle (no transformer and no effect)
190 this->disable_loop_if_idle_();
191 }
192}
193
195 // Either would write its own values over the reported ones
196 if (this->next_write_ || this->transformer_ != nullptr) {
197 return false;
198 }
199 const bool had_effect = this->active_effect_index_ != 0;
200 this->stop_effect_(); // schedules no write, unlike a call that sets effect 0
201 if (!had_effect && values == this->remote_values && values == this->current_values) {
202 return true; // nothing new to tell
203 }
204 this->current_values = values;
205 this->remote_values = values;
206 // Reached at once, as after an instant call, and told before the publish like there: an
207 // automation run by the publish may change the light again, and its own call reports that
209 for (auto *listener : *this->target_state_reached_listeners_) {
210 listener->on_light_target_state_reached();
211 }
212 }
213 this->publish_state();
214 return true;
215}
216
218 if (this->remote_values_listeners_) {
219 for (auto *listener : *this->remote_values_listeners_) {
220 listener->on_light_remote_values_update();
221 }
222 }
223#if defined(USE_LIGHT) && defined(USE_CONTROLLER_REGISTRY)
224 ControllerRegistry::notify_light_update(this);
225#endif
226}
227
229
231 if (this->active_effect_index_ > 0) {
232 return this->effects_[this->active_effect_index_ - 1]->get_name();
233 }
234 return EFFECT_NONE_REF;
235}
236
238 if (!this->remote_values_listeners_) {
239 this->remote_values_listeners_ = make_unique<std::vector<LightRemoteValuesListener *>>();
240 }
241 this->remote_values_listeners_->push_back(listener);
242}
245 this->target_state_reached_listeners_ = make_unique<std::vector<LightTargetStateReachedListener *>>();
246 }
247 this->target_state_reached_listeners_->push_back(listener);
248}
249
251 this->current_values.as_brightness(brightness);
252 *brightness = this->gamma_correct_lut(*brightness);
253}
254void LightState::current_values_as_rgb(float *red, float *green, float *blue) {
255 this->current_values.as_rgb(red, green, blue);
256 *red = this->gamma_correct_lut(*red);
257 *green = this->gamma_correct_lut(*green);
258 *blue = this->gamma_correct_lut(*blue);
259}
260void LightState::current_values_as_rgbw(float *red, float *green, float *blue, float *white) {
261 this->current_values.as_rgbw(red, green, blue, white);
262 *red = this->gamma_correct_lut(*red);
263 *green = this->gamma_correct_lut(*green);
264 *blue = this->gamma_correct_lut(*blue);
265 *white = this->gamma_correct_lut(*white);
266}
267void LightState::current_values_as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white,
268 bool constant_brightness) {
269 this->current_values.as_rgb(red, green, blue);
270 *red = this->gamma_correct_lut(*red);
271 *green = this->gamma_correct_lut(*green);
272 *blue = this->gamma_correct_lut(*blue);
273 this->current_values_as_cwww(cold_white, warm_white, constant_brightness);
274}
275void LightState::current_values_as_rgbct(float *red, float *green, float *blue, float *color_temperature,
276 float *white_brightness) {
277 auto traits = this->get_traits();
278 this->current_values.as_rgbct(traits.get_min_mireds(), traits.get_max_mireds(), red, green, blue, color_temperature,
279 white_brightness);
280 *red = this->gamma_correct_lut(*red);
281 *green = this->gamma_correct_lut(*green);
282 *blue = this->gamma_correct_lut(*blue);
283 *white_brightness = this->gamma_correct_lut(*white_brightness);
284}
285void LightState::current_values_as_cwww(float *cold_white, float *warm_white, bool constant_brightness) {
286 if (!constant_brightness) {
287 // Without constant_brightness, gamma commutes with simple multiplication:
288 // gamma(white_level * cw) = gamma(white_level) * gamma(cw)
289 // (since gamma(a*b) = (a*b)^g = a^g * b^g = gamma(a) * gamma(b))
290 // so applying gamma after is mathematically equivalent and simpler.
291 this->current_values.as_cwww(cold_white, warm_white, false);
292 *cold_white = this->gamma_correct_lut(*cold_white);
293 *warm_white = this->gamma_correct_lut(*warm_white);
294 return;
295 }
296
297 // For constant_brightness mode, gamma MUST be applied to the individual
298 // channel values BEFORE the balancing formula (max/sum ratio), not after.
299 //
300 // Why: The cold_white_ and warm_white_ values stored in LightColorValues
301 // are gamma-uncorrected (see transform_parameters_() which applies
302 // gamma_uncorrect to the linear CW/WW fractions derived from color
303 // temperature). Applying gamma_correct here recovers the original linear
304 // fractions, which the constant_brightness formula then uses to distribute
305 // power evenly. The max/sum formula ensures cold+warm PWM output sums to
306 // a constant, keeping total power (and perceived brightness) the same
307 // across all color temperatures.
308 //
309 // Applying gamma AFTER the formula would be incorrect because gamma is
310 // nonlinear: gamma(a/b) != gamma(a)/gamma(b), so the carefully balanced
311 // ratio would be distorted, causing a severe brightness dip at mid-range
312 // color temperatures.
313 const auto &v = this->current_values;
314 if (!(v.get_color_mode() & ColorCapability::COLD_WARM_WHITE)) {
315 *cold_white = *warm_white = 0;
316 return;
317 }
318
319 const float cw_level = this->gamma_correct_lut(v.get_cold_white());
320 const float ww_level = this->gamma_correct_lut(v.get_warm_white());
321 const float white_level = this->gamma_correct_lut(v.get_state() * v.get_brightness());
322 const float sum = cw_level > 0 || ww_level > 0 ? cw_level + ww_level : 1; // Don't divide by zero.
323 *cold_white = white_level * std::max(cw_level, ww_level) * cw_level / sum;
324 *warm_white = white_level * std::max(cw_level, ww_level) * ww_level / sum;
325}
326void LightState::current_values_as_ct(float *color_temperature, float *white_brightness) {
327 auto traits = this->get_traits();
328 this->current_values.as_ct(traits.get_min_mireds(), traits.get_max_mireds(), color_temperature, white_brightness);
329 *white_brightness = this->gamma_correct_lut(*white_brightness);
330}
331
333#ifdef USE_LIGHT_GAMMA_LUT
334 if (this->gamma_table_ != nullptr)
335 return progmem_read_uint16(&this->gamma_table_->gamma_x100) * 0.01f;
336#endif // USE_LIGHT_GAMMA_LUT
337 return 0.0f;
338}
339
340#ifdef USE_LIGHT_GAMMA_LUT
341float LightState::gamma_correct_lut(float value) const {
342 if (value <= 0.0f)
343 return 0.0f;
344 if (value >= 1.0f)
345 return 1.0f;
346 if (this->gamma_table_ == nullptr)
347 return value;
348 float scaled = value * 255.0f;
349 auto idx = static_cast<uint8_t>(scaled);
350 if (idx >= 255)
351 return progmem_read_uint16(&this->gamma_table_->lut[255]) / 65535.0f;
352 float frac = scaled - idx;
353 float a = progmem_read_uint16(&this->gamma_table_->lut[idx]);
354 float b = progmem_read_uint16(&this->gamma_table_->lut[idx + 1]);
355 return (a + frac * (b - a)) / 65535.0f;
356}
357float LightState::gamma_uncorrect_lut(float value) const {
358 if (value <= 0.0f)
359 return 0.0f;
360 if (value >= 1.0f)
361 return 1.0f;
362 if (this->gamma_table_ == nullptr)
363 return value;
364 uint16_t target = static_cast<uint16_t>(value * 65535.0f);
365 uint8_t lo = gamma_table_reverse_search(this->gamma_table_->lut, target);
366 if (lo >= 255)
367 return 1.0f;
368 // Interpolate between lo and lo+1
369 uint16_t a = progmem_read_uint16(&this->gamma_table_->lut[lo]);
370 uint16_t b = progmem_read_uint16(&this->gamma_table_->lut[lo + 1]);
371 if (b == a)
372 return lo / 255.0f;
373 float frac = static_cast<float>(target - a) / static_cast<float>(b - a);
374 return (lo + frac) / 255.0f;
375}
376#endif // USE_LIGHT_GAMMA_LUT
377
379 this->stop_effect_();
380 if (effect_index == 0)
381 return;
382
383 this->active_effect_index_ = static_cast<uint16_t>(effect_index);
384 auto *effect = this->get_active_effect_();
385 effect->start_internal();
386 // Enable loop while effect is active
387 this->enable_loop();
388}
390 if (this->active_effect_index_ == 0) {
391 return nullptr;
392 } else {
393 return this->effects_[this->active_effect_index_ - 1];
394 }
395}
397 auto *effect = this->get_active_effect_();
398 if (effect != nullptr) {
399 effect->stop();
400 }
401 this->active_effect_index_ = 0;
402 // Disable loop if idle (no effect and no transformer)
403 this->disable_loop_if_idle_();
404}
405
406void LightState::start_transition_(const LightColorValues &target, uint32_t length, bool set_remote_values) {
408 this->transformer_->setup(this->current_values, target, length);
409 this->set_transformer_remote_values_(target, set_remote_values);
410 // Enable loop while transition is active
411 this->enable_loop();
412}
413
414void LightState::start_flash_(const LightColorValues &target, uint32_t length, bool set_remote_values) {
415 LightColorValues end_colors = this->remote_values;
416 // If starting a flash if one is already happening, set end values to end values of current flash
417 // Hacky but works
418 if (this->transformer_ != nullptr)
419 end_colors = this->transformer_->get_start_values();
420
421 this->transformer_ = make_unique<LightFlashTransformer>(*this);
422 this->transformer_->setup(end_colors, target, length);
423 this->set_transformer_remote_values_(target, set_remote_values);
424 // Enable loop while flash is active
425 this->enable_loop();
426}
427
428void LightState::set_immediately_(const LightColorValues &target, bool set_remote_values) {
429 this->is_transformer_active_ = false;
430 this->transformer_ = nullptr;
431#ifdef USE_LIGHT_TRANSITION_PUBLISH_INTERVAL
432 this->transition_publish_enabled_ = false;
433#endif
434 this->current_values = target;
435 if (set_remote_values) {
436 this->remote_values = target;
437 }
438 this->output_->update_state(this);
439 this->schedule_write_();
440}
441
443 // Only disable loop if both transformer and effect are inactive, and no pending writes
444 if (this->transformer_ == nullptr && this->get_active_effect_() == nullptr && !this->next_write_) {
445 this->disable_loop();
446 }
447}
448
449#ifdef USE_LIGHT_TRANSITION_PUBLISH_INTERVAL
450void LightState::set_transformer_remote_values_(const LightColorValues &target, bool set_remote_values) {
451 this->transition_publish_enabled_ = set_remote_values && this->transition_state_publish_interval_ > 0;
452 if (this->transition_publish_enabled_) {
454 }
455 if (set_remote_values) {
456 this->remote_values = target;
457 }
458}
459#endif
460
462 if (!this->save_enabled_)
463 return;
464 LightStateRTCState saved;
466 // Always the real on/off status (RESTORE_AND_ON/OFF used to persist a hardcoded
467 // true/false here instead; harmless, since those modes force `state` again on
468 // every load regardless of what was saved -- see _legacy_restore_statements).
469 saved.state = this->remote_values.is_on();
472 saved.red = this->remote_values.get_red();
473 saved.green = this->remote_values.get_green();
474 saved.blue = this->remote_values.get_blue();
475 saved.white = this->remote_values.get_white();
479 saved.effect = static_cast<uint32_t>(this->active_effect_index_); // the saved layout stays uint32_t
480 this->rtc_.save(&saved);
481}
482
483} // namespace esphome::light
BedjetMode mode
BedJet operating mode.
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
void enable_loop()
Enable this component's loop.
Definition component.h:248
void disable_loop()
Disable this component's loop.
const LogString * get_log_name() const
Get the name for a "%s" log argument (LOG_STR_ARG).
ESPPreferenceObject make_entity_preference(uint32_t version=0)
Create a preference object for storing this entity's state/settings.
StringRef is a reference to a string owned by something else.
Definition string_ref.h:31
This class represents a requested change in a light state.
Definition light_call.h:23
LightCall & set_state(optional< bool > state)
Set the binary ON/OFF state of the light.
This class represents the color state for a light object.
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.
void as_cwww(float *cold_white, float *warm_white, bool constant_brightness=false) const
Convert these light color values to an CWWW representation with the given parameters.
float get_cold_white() const
Get the cold white property of these light color values. In range 0.0 to 1.0.
void as_rgbw(float *red, float *green, float *blue, float *white) const
Convert these light color values to an RGBW representation and write them to red, green,...
void as_rgb(float *red, float *green, float *blue) const
Convert these light color values to an RGB representation and write them to red, green,...
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.
void set_color_temperature(float color_temperature)
Set the color temperature property of these light color values in mired.
float get_warm_white() const
Get the warm white property of these light color values. In range 0.0 to 1.0.
void as_ct(float color_temperature_cw, float color_temperature_ww, float *color_temperature, float *white_brightness) const
Convert these light color values to a CT+BR representation with the given parameters.
ColorMode get_color_mode() const
Get the color mode of these light color values.
void as_rgbct(float color_temperature_cw, float color_temperature_ww, float *red, float *green, float *blue, float *color_temperature, float *white_brightness) const
Convert these light color values to an RGB+CT+BR representation with the given parameters.
float get_red() const
Get the red property of these light color values. In range 0.0 to 1.0.
void as_brightness(float *brightness) const
Convert these light color values to a brightness-only representation and write them to brightness.
float get_color_brightness() const
Get the color brightness property of these light color values. In range 0.0 to 1.0.
Interface to write LightStates to hardware.
virtual void write_state(LightState *state)=0
Called from loop() every time the light state has changed, and should should write the new state to h...
virtual std::unique_ptr< LightTransformer > create_default_transition()
Return the default transformer used for transitions.
virtual LightTraits get_traits()=0
Return the LightTraits of this LightOutput.
virtual void update_state(LightState *state)
Called on every update of the current values of the associated LightState, can optionally be used to ...
virtual void setup_state(LightState *state)
Listener interface for light remote value changes.
Definition light_state.h:32
void add_remote_values_listener(LightRemoteValuesListener *listener)
Add a listener for remote values changes.
StringRef get_effect_name()
Return the name of the current effect, or if no effect is active "None".
void start_effect_(uint32_t effect_index)
Internal method to start an effect with the given index.
void current_values_as_rgb(float *red, float *green, float *blue)
float gamma_correct_lut(float value) const
Apply gamma correction using the pre-computed forward LUT.
void stop_effect_()
Internal method to stop the current effect (if one is active).
void current_values_as_rgbct(float *red, float *green, float *blue, float *color_temperature, float *white_brightness)
void disable_loop_if_idle_()
Disable loop if neither transformer nor effect is active.
std::unique_ptr< LightTransformer > transformer_
The currently active transformer for this light (transition/flash).
void dump_config() override
bool transition_publish_enabled_
True while the active transformer publishes current_values on an interval from loop().
LightColorValues remote_values
The remote color values reported to the frontend.
LightOutput * get_output() const
Get the light output associated with this object.
void(* state_callback_)(LightStateRTCState &, bool restored)
Callback that resolves the boot-time state — called once during setup, then cleared.
LightState(LightOutput *output)
void save_remote_values_()
Internal method to save the current remote_values to the preferences.
void add_target_state_reached_listener(LightTargetStateReachedListener *listener)
Add a listener for target state reached.
LightCall turn_on()
Make a light state call.
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
The gamma correction factor, read from the entry after the gamma lookup table; 0 without one.
bool set_external_state(const LightColorValues &values)
Take over the state of a light mirrored from elsewhere: current and target values at once,...
void current_values_as_ct(float *color_temperature, float *white_brightness)
float gamma_uncorrect_lut(float value) const
Reverse gamma correction by binary-searching the forward LUT.
void current_values_as_cwww(float *cold_white, float *warm_white, bool constant_brightness=false)
void publish_state()
Publish the currently active state to the frontend.
void current_values_as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white, bool constant_brightness=false)
ConstVector< LightEffect * > effects_
List of effects for this light.
void current_values_as_brightness(float *brightness)
void setup() override
Load state from preferences.
const GammaTable * gamma_table_
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.
uint32_t transition_state_publish_interval_
void schedule_write_()
Schedule a write to the light output and enable the loop to process it.
uint16_t previous_effect_index_
The effect index that was active when the light was last turned off; shares the active index's word.
bool next_write_
Whether the light value should be written in the next cycle.
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.
bool save_enabled_
Whether this light persists its state to preferences at all.
LightOutput * output_
Store the output to allow effects to have more access.
ESPPreferenceObject rtc_
Object used to store the persisted values of the light.
uint16_t active_effect_index_
1-based index of the active effect, 0 if none; codegen caps effects at MAX_EFFECTS in effects....
void current_values_as_rgbw(float *red, float *green, float *blue, float *white)
uint32_t default_transition_length_
Default transition length for all transitions in ms.
LightColorValues current_values
The current values of the light as outputted to the light.
LightEffect * get_active_effect_()
Internal method to get the currently active effect.
std::unique_ptr< std::vector< LightRemoteValuesListener * > > remote_values_listeners_
Listeners for remote values changes.
std::unique_ptr< std::vector< LightTargetStateReachedListener * > > target_state_reached_listeners_
Listeners for target state reached.
uint32_t last_transition_state_publish_
void set_transformer_remote_values_(const LightColorValues &target, bool set_remote_values)
Point remote_values at the new transformer's target and, when this light publishes intermediate state...
Listener interface for light target state reached.
Definition light_state.h:43
This class is used to represent the capabilities of a light.
Definition light_traits.h:9
constexpr StringRef EFFECT_NONE_REF
Definition light_effect.h:8
ESPHOME_LOG_TAG(TAG, "light.addressable")
uint8_t gamma_table_reverse_search(const uint16_t *table, uint16_t target)
Binary search a monotonically increasing uint16[256] PROGMEM table.
static float float b
ColorMode
Color modes are a combination of color capabilities that can be used at the same time.
Definition color_mode.h:50
@ UNKNOWN
No color mode configured (cannot be a supported mode, only active when light is off).
@ BRIGHTNESS
Master brightness of the light can be controlled.
@ COLOR_TEMPERATURE
Color temperature can be controlled.
@ COLD_WARM_WHITE
Brightness of cold and warm white output can be controlled.
uint16_t progmem_read_uint16(const uint16_t *addr)
Definition hal.h:53
Application App
Global storage of Application pointer - only one Application can exist.
uint16_t length
Definition tt21100.cpp:0