ESPHome 2026.10.0
Loading...
Searching...
No Matches
light_state.h
Go to the documentation of this file.
1#pragma once
2
8#include "light_call.h"
10#include "light_color_values.h"
11#include "light_effect.h"
12#include "light_traits.h"
13#include "light_transformer.h"
14
15#include "esphome/core/hal.h"
18#include <strings.h>
19#include <vector>
20
21namespace esphome::light {
22
23class LightOutput;
24class LightState;
25
33 public:
35};
36
44 public:
46};
47
49 // Group 4-byte aligned members first
50 float brightness{1.0f};
51 float color_brightness{1.0f};
52 float red{1.0f};
53 float green{1.0f};
54 float blue{1.0f};
55 float white{1.0f};
56 float color_temp{1.0f};
57 float cold_white{1.0f};
58 float warm_white{1.0f};
60 // Group smaller members at the end
62 bool state{false};
63};
64
68class LightState : public EntityBase, public Component {
69 public:
70 LightState(LightOutput *output);
71
73
78
83#ifdef USE_LIGHT_TRANSITION_PUBLISH_INTERVAL
85 return this->current_values;
86 }
87#endif
88 return this->remote_values;
89 }
90
92 bool is_transitioning() const { return this->transformer_ != nullptr; }
94
95 // ========== INTERNAL METHODS ==========
96 // (In most use cases you won't need these)
98 void setup() override;
99 void dump_config() override;
100 void loop() override;
102 float get_setup_priority() const override { return setup_priority::HARDWARE - 1.0f; }
103
115
127
129 void publish_state();
130
132 LightOutput *get_output() const;
133
136
142
148
150 void set_default_transition_length(uint32_t default_transition_length) {
151 this->default_transition_length_ = default_transition_length;
152 }
154
155#ifdef USE_LIGHT_FLASH_TRANSITION_LENGTH
157 void set_flash_transition_length(uint32_t flash_transition_length) {
158 this->flash_transition_length_ = flash_transition_length;
159 }
161#else
162 // Remove before 2027.4.0
163 ESPDEPRECATED("set_flash_transition_length() does nothing unless flash_transition_length is set in YAML. Removed in "
164 "2027.4.0",
165 "2026.10.0")
166 void set_flash_transition_length(uint32_t flash_transition_length) {}
168#endif
169
170 // Remove before 2027.4.0
171 ESPDEPRECATED("set_gamma_correct() does nothing; gamma is fixed at build time by gamma_correct in YAML. Removed in "
172 "2027.4.0",
173 "2026.10.0")
174 void set_gamma_correct(float gamma_correct) {}
176 float get_gamma_correct() const;
177
178#ifdef USE_LIGHT_TRANSITION_PUBLISH_INTERVAL
179 void set_transition_state_publish_interval(uint32_t transition_state_publish_interval) {
180 this->transition_state_publish_interval_ = transition_state_publish_interval;
181 }
183#endif
184
185#ifdef USE_LIGHT_GAMMA_LUT
187 void set_gamma_table(const GammaTable *table) { this->gamma_table_ = table; }
188
190 const uint16_t *get_gamma_table() const { return this->gamma_table_ != nullptr ? this->gamma_table_->lut : nullptr; }
191
193 float gamma_correct_lut(float value) const;
195 float gamma_uncorrect_lut(float value) const;
196#else
198 float gamma_correct_lut(float value) const { return value; }
199 float gamma_uncorrect_lut(float value) const { return value; }
200#endif // USE_LIGHT_GAMMA_LUT
201
206 void set_state_callback(void (*callback)(LightStateRTCState &, bool restored)) { this->state_callback_ = callback; }
207
209 void set_save_enabled(bool save_enabled) { this->save_enabled_ = save_enabled; }
210
211#ifdef USE_LIGHT_RESUME_EFFECT
213 void set_resume_effect(bool resume_effect) { this->resume_effect_ = resume_effect; }
214#endif // USE_LIGHT_RESUME_EFFECT
215
217 bool supports_effects() const { return !this->effects_.empty(); }
218
220 const FixedVector<LightEffect *> &get_effects() const { return this->effects_; }
221
223 void add_effects(const std::initializer_list<LightEffect *> &effects);
224
226 size_t get_effect_count() const { return this->effects_.size(); }
227
230
232 uint32_t get_effect_index(const std::string &effect_name) const {
233 if (str_equals_case_insensitive(effect_name, "none")) {
234 return 0;
235 }
236 for (size_t i = 0; i < this->effects_.size(); i++) {
237 if (str_equals_case_insensitive(effect_name, this->effects_[i]->get_name())) {
238 return i + 1; // Effects are 1-indexed in active_effect_index_
239 }
240 }
241 return 0; // Effect not found
242 }
243
245 uint32_t get_effect_index(const char *name, size_t len) const {
246 if (len == 4 && ESPHOME_strncasecmp_P(name, ESPHOME_PSTR("none"), 4) == 0) {
247 return 0;
248 }
249 StringRef ref(name, len);
250 for (size_t i = 0; i < this->effects_.size(); i++) {
251 if (str_equals_case_insensitive(ref, this->effects_[i]->get_name())) {
252 return i + 1;
253 }
254 }
255 return 0;
256 }
257
260 if (index == 0 || index > this->effects_.size()) {
261 return nullptr;
262 }
263 return this->effects_[index - 1]; // Effects are 1-indexed in active_effect_index_
264 }
265
267 std::string get_effect_name_by_index(uint32_t index) const {
268 if (index == 0) {
269 return "None";
270 }
271 if (index > this->effects_.size()) {
272 return ""; // Invalid index
273 }
274 return std::string(this->effects_[index - 1]->get_name());
275 }
276
278 void current_values_as_binary(bool *binary) { this->current_values.as_binary(binary); }
279
280 void current_values_as_brightness(float *brightness);
281
282 void current_values_as_rgb(float *red, float *green, float *blue);
283
284 void current_values_as_rgbw(float *red, float *green, float *blue, float *white);
285
286 void current_values_as_rgbww(float *red, float *green, float *blue, float *cold_white, float *warm_white,
287 bool constant_brightness = false);
288
289 void current_values_as_rgbct(float *red, float *green, float *blue, float *color_temperature,
290 float *white_brightness);
291
292 void current_values_as_cwww(float *cold_white, float *warm_white, bool constant_brightness = false);
293
294 void current_values_as_ct(float *color_temperature, float *white_brightness);
295
305 bool is_transformer_active() const { return this->is_transformer_active_; }
306
307 protected:
309 friend LightCall;
310 friend class AddressableLight;
312
314 void start_effect_(uint32_t effect_index);
318 void stop_effect_();
320 void start_transition_(const LightColorValues &target, uint32_t length, bool set_remote_values);
321
323 void start_flash_(const LightColorValues &target, uint32_t length, bool set_remote_values);
324
326 void set_immediately_(const LightColorValues &target, bool set_remote_values);
327
330#ifdef USE_LIGHT_TRANSITION_PUBLISH_INTERVAL
331 void set_transformer_remote_values_(const LightColorValues &target, bool set_remote_values);
332#else
333 void set_transformer_remote_values_(const LightColorValues &target, bool set_remote_values) {
334 if (set_remote_values) {
335 this->remote_values = target;
336 }
337 }
338#endif
339
341 void save_remote_values_();
342
345
348 this->next_write_ = true;
349 this->enable_loop();
350 }
351
355 std::unique_ptr<LightTransformer> transformer_{nullptr};
360
370 std::unique_ptr<std::vector<LightRemoteValuesListener *>> remote_values_listeners_;
371
378 std::unique_ptr<std::vector<LightTargetStateReachedListener *>> target_state_reached_listeners_;
379
382 void (*state_callback_)(LightStateRTCState &, bool restored){nullptr};
383
386#ifdef USE_LIGHT_FLASH_TRANSITION_LENGTH
388 uint32_t flash_transition_length_{}; // Keep in sync with DEFAULT_FLASH_TRANSITION_LENGTH in __init__.py
389#endif
390#ifdef USE_LIGHT_TRANSITION_PUBLISH_INTERVAL
393#endif
394#ifdef USE_LIGHT_GAMMA_LUT
395 const GammaTable *gamma_table_{nullptr};
396#endif // USE_LIGHT_GAMMA_LUT
397
400#ifdef USE_LIGHT_RESUME_EFFECT
403#endif // USE_LIGHT_RESUME_EFFECT
405 bool next_write_{true}; // a plain bool: it is the most written flag, and still shares the index's word
406 // for effects, true if a transformer (transition) is active.
407 bool is_transformer_active_ : 1 {false};
409 bool save_enabled_ : 1 {false};
410#ifdef USE_LIGHT_TRANSITION_PUBLISH_INTERVAL
413#endif
414#ifdef USE_LIGHT_RESUME_EFFECT
416 bool resume_effect_ : 1 {false};
417#endif // USE_LIGHT_RESUME_EFFECT
418};
419
420} // namespace esphome::light
void enable_loop()
Enable this component's loop.
Definition component.h:246
const StringRef & get_name() const
Definition entity_base.h:71
Fixed-capacity vector - sized once through init() or try_init(); push_back never reallocates This avo...
Definition helpers.h:621
StringRef is a reference to a string owned by something else.
Definition string_ref.h:30
This class represents a requested change in a light state.
Definition light_call.h:22
This class represents the color state for a light object.
void as_binary(bool *binary) const
Convert these light color values to a binary representation and write them to binary.
Interface to write LightStates to hardware.
Listener interface for light remote value changes.
Definition light_state.h:32
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
Definition light_state.h:68
void add_remote_values_listener(LightRemoteValuesListener *listener)
Add a listener for remote values changes.
uint32_t get_transition_state_publish_interval() const
FixedVector< LightEffect * > effects_
List of effects for this light.
StringRef get_effect_name()
Return the name of the current effect, or if no effect is active "None".
bool resume_effect_
Whether a plain turn-on restores the effect that was active when the light was turned off.
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)
std::string get_effect_name_by_index(uint32_t index) const
Get effect name by index. Returns "None" for index 0, empty string for invalid index.
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).
bool supports_effects() const
Return whether the light has any effects that meet the trait requirements.
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 set_save_enabled(bool save_enabled)
Set whether this light persists its state to preferences at all.
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.
uint32_t get_current_effect_index() const
Get the currently active effect index (0 = no effect, 1+ = effect index).
LightOutput * get_output() const
Get the light output associated with this object.
const LightColorValues & get_reported_values() const
The values reported to the frontend: current_values while a light publishes intermediate states on an...
Definition light_state.h:82
void set_flash_transition_length(uint32_t flash_transition_length)
Set the flash transition length; only compiled in when a light configures one.
ESPDEPRECATED("set_flash_transition_length() does nothing unless flash_transition_length is set in YAML. Removed in " "2027.4.0", "2026.10.0") void set_flash_transition_length(uint32_t flash_transition_length)
void(* state_callback_)(LightStateRTCState &, bool restored)
Callback that resolves the boot-time state — called once during setup, then cleared.
LightState(LightOutput *output)
void current_values_as_binary(bool *binary)
The result of all the current_values_as_* methods have gamma correction applied.
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.
uint32_t get_default_transition_length() const
void set_immediately_(const LightColorValues &target, bool set_remote_values)
Internal method to set the color values to target immediately (with no transition).
bool is_transitioning() const
True from the call that starts a transition or flash until it reaches its target.
Definition light_state.h:92
uint32_t get_flash_transition_length() const
ESPDEPRECATED("set_gamma_correct() does nothing; gamma is fixed at build time by gamma_correct in YAML. Removed in " "2027.4.0", "2026.10.0") void set_gamma_correct(float gamma_correct)
float get_gamma_correct() const
The gamma correction factor, read from the entry after the gamma lookup table; 0 without one.
uint32_t get_effect_index(const std::string &effect_name) const
Get effect index by name. Returns 0 if effect not found.
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)
uint32_t flash_transition_length_
Transition length to use for flash transitions.
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)
void current_values_as_brightness(float *brightness)
void setup() override
Load state from preferences.
LightEffect * get_effect_by_index(uint32_t index) const
Get effect by index. Returns nullptr if index is invalid.
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.
void set_resume_effect(bool resume_effect)
Set whether a plain turn-on restores the effect that was active when the light was turned off.
bool is_transformer_active() const
Indicator if a transformer (e.g.
const FixedVector< LightEffect * > & get_effects() const
Get all effects for this light state.
void set_transition_state_publish_interval(uint32_t transition_state_publish_interval)
uint32_t transition_state_publish_interval_
void add_effects(const std::initializer_list< LightEffect * > &effects)
Add effects for this light state.
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.
const uint16_t * get_gamma_table() const
Get the forward gamma lookup table, 256 PROGMEM entries.
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.
float get_setup_priority() const override
Shortly after HARDWARE.
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.
void set_gamma_table(const GammaTable *table)
Set the pre-computed PROGMEM gamma curve.
void set_state_callback(void(*callback)(LightStateRTCState &, bool restored))
Set the callback that resolves the boot-time state, called once during setup then cleared.
LightColorValues current_values
The current values of the light as outputted to the light.
uint32_t get_effect_index(const char *name, size_t len) const
Get effect index by name (const char* overload, avoids std::string construction).
LightEffect * get_active_effect_()
Internal method to get the currently active effect.
size_t get_effect_count() const
Get the total number of effects available for this light.
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_default_transition_length(uint32_t default_transition_length)
Set the default transition length, i.e. the transition length when no transition is provided.
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
ColorMode
Color modes are a combination of color capabilities that can be used at the same time.
Definition color_mode.h:49
@ UNKNOWN
No color mode configured (cannot be a supported mode, only active when light is off).
constexpr float HARDWARE
For components that deal with hardware and are very important like GPIO switch.
Definition component.h:43
const void size_t len
Definition hal.h:64
bool str_equals_case_insensitive(const std::string &a, const std::string &b)
Compare strings for equality in case-insensitive manner.
Definition helpers.cpp:209
A gamma curve as codegen emits it into PROGMEM: the lookup table and the gamma it was built from.
uint16_t length
Definition tt21100.cpp:0