ESPHome 2026.11.0-dev
Loading...
Searching...
No Matches
base_light_effects.h
Go to the documentation of this file.
1#pragma once
2
3#include <type_traits>
4#include <utility>
5
7#include "esphome/core/hal.h"
9#include "light_effect.h"
10
11namespace esphome::light {
12
13inline static float random_cubic_float() {
14 const float r = random_float() * 2.0f - 1.0f;
15 return r * r * r;
16}
17
20 public:
21 explicit PulseLightEffect(const char *name) : LightEffect(name) {}
22
23 void apply() override {
24 const uint32_t now = millis();
26 return;
27 }
28 auto call = this->state_->turn_on();
29 float out = this->on_ ? this->max_brightness_ : this->min_brightness_;
30 call.set_brightness_if_supported(out);
31 call.set_transition_length_if_supported(this->on_ ? this->transition_on_length_ : this->transition_off_length_);
32 this->on_ = !this->on_;
33 // don't tell HA every change
34 call.set_publish(false);
35 call.set_save(false);
36 call.perform();
37
38 this->last_color_change_ = now;
39 }
40
41 void set_transition_on_length(uint32_t transition_length) { this->transition_on_length_ = transition_length; }
42 void set_transition_off_length(uint32_t transition_length) { this->transition_off_length_ = transition_length; }
43
44 void set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; }
45
46 void set_min_max_brightness(float min, float max) {
47 this->min_brightness_ = min;
48 this->max_brightness_ = max;
49 }
50
51 protected:
52 bool on_ = false;
57 float min_brightness_{0.0};
58 float max_brightness_{1.0};
59};
60
63 public:
64 explicit RandomLightEffect(const char *name) : LightEffect(name) {}
65
66 void apply() override {
67 const uint32_t now = millis();
69 return;
70 }
71
72 auto color_mode = this->state_->remote_values.get_color_mode();
73 auto call = this->state_->turn_on();
74 bool changed = false;
75 if (color_mode & ColorCapability::RGB) {
76 call.set_red(random_float());
77 call.set_green(random_float());
78 call.set_blue(random_float());
79 changed = true;
80 }
81 if (color_mode & ColorCapability::COLOR_TEMPERATURE) {
82 float min = this->state_->get_traits().get_min_mireds();
83 float max = this->state_->get_traits().get_max_mireds();
84 call.set_color_temperature(min + random_float() * (max - min));
85 changed = true;
86 }
87 if (color_mode & ColorCapability::COLD_WARM_WHITE) {
88 call.set_cold_white(random_float());
89 call.set_warm_white(random_float());
90 changed = true;
91 }
92 if (!changed) {
93 // only randomize brightness if there's no colored option available
94 call.set_brightness(random_float());
95 }
97 call.set_publish(true);
98 call.set_save(false);
99 call.perform();
100
101 this->last_color_change_ = now;
102 }
103
104 void set_transition_length(uint32_t transition_length) { this->transition_length_ = transition_length; }
105
106 void set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; }
107
108 protected:
112};
113
115 public:
116 LambdaLightEffect(const char *name, void (*f)(LightState &, bool initial_run), uint32_t update_interval)
117 : LightEffect(name), f_(f), update_interval_(update_interval) {}
118
119 void start() override { this->initial_run_ = true; }
120 void apply() override {
121 const uint32_t now = millis();
122 if (now - this->last_run_ >= this->update_interval_ || this->initial_run_) {
123 this->last_run_ = now;
124 this->f_(*this->state_, this->initial_run_);
125 this->initial_run_ = false;
126 }
127 }
128
131 uint32_t get_current_index() const { return this->get_index(); }
132
133 protected:
134 void (*f_)(LightState &, bool initial_run);
138};
139
141 public:
142 AutomationLightEffect(const char *name) : LightEffect(name) {}
143 void stop() override { this->trig_.stop_action(); }
144 void apply() override {
145 if (!this->trig_.is_action_running()) {
146 this->trig_.trigger();
147 }
148 }
149 Trigger<> *get_trig() { return &this->trig_; }
150
153 uint32_t get_current_index() const { return this->get_index(); }
154
155 protected:
157};
158
175static_assert(std::is_trivially_copyable_v<StrobeLightEffectColor>, "StrobeLightEffectColor is copied out of flash");
176static_assert(sizeof(StrobeLightEffectColor) % sizeof(uint32_t) == 0,
177 "StrobeLightEffectColor must be whole words for ESP8266 flash reads");
178
180 public:
181 explicit StrobeLightEffect(const char *name) : LightEffect(name) {}
182 void start() override {
183 // Place the cycle at the end of the last color, so the first apply() switches straight to the first color
184 this->at_color_ = this->colors_.size() - 1;
185 this->last_switch_ = millis() - this->duration_(this->at_color_);
186 }
187 void apply() override {
188 const uint32_t now = millis();
189 if (now - this->last_switch_ < this->duration_(this->at_color_))
190 return;
191
192 // Switch to next color
193 this->at_color_ = (this->at_color_ + 1) % this->colors_.size();
195 progmem_memcpy(&step, &this->colors_[this->at_color_], sizeof(step));
196 LightColorValues color(step.color_mode, step.state, step.brightness, step.color_brightness, step.red, step.green,
197 step.blue, step.white, step.color_temperature, step.cold_white, step.warm_white);
198
199 auto call = this->state_->turn_on();
200 call.from_light_color_values(color);
201
202 if (!color.is_on()) {
203 // Don't turn the light off, otherwise the light effect will be stopped
204 call.set_brightness(0.0f);
205 call.set_state(true);
206 }
207 call.set_publish(false);
208 call.set_save(false);
210 call.perform();
211 this->last_switch_ = now;
212 }
213
215 void set_colors(const StrobeLightEffectColor *colors, size_t count) { this->colors_ = {colors, count}; }
216
217 protected:
218 uint32_t duration_(size_t index) const {
220 progmem_memcpy(&duration, &this->colors_[index].duration, sizeof(duration));
221 return duration;
222 }
223
226 size_t at_color_{0};
227};
228
230 public:
231 explicit FlickerLightEffect(const char *name) : LightEffect(name) {}
232
233 void apply() override {
234 LightColorValues remote = this->state_->remote_values;
235 LightColorValues current = this->state_->current_values;
237 const float alpha = this->alpha_;
238 const float beta = 1.0f - alpha;
239 out.set_state(true);
240 out.set_brightness(remote.get_brightness() * beta + current.get_brightness() * alpha +
241 (random_cubic_float() * this->intensity_));
242 out.set_red(remote.get_red() * beta + current.get_red() * alpha + (random_cubic_float() * this->intensity_));
243 out.set_green(remote.get_green() * beta + current.get_green() * alpha + (random_cubic_float() * this->intensity_));
244 out.set_blue(remote.get_blue() * beta + current.get_blue() * alpha + (random_cubic_float() * this->intensity_));
245 out.set_white(remote.get_white() * beta + current.get_white() * alpha + (random_cubic_float() * this->intensity_));
246 out.set_cold_white(remote.get_cold_white() * beta + current.get_cold_white() * alpha +
247 (random_cubic_float() * this->intensity_));
248 out.set_warm_white(remote.get_warm_white() * beta + current.get_warm_white() * alpha +
249 (random_cubic_float() * this->intensity_));
250
251 auto call = this->state_->make_call();
252 call.set_publish(false);
253 call.set_save(false);
256 call.set_state(true);
257 call.perform();
258 }
259
260 void set_alpha(float alpha) { this->alpha_ = alpha; }
261 void set_intensity(float intensity) { this->intensity_ = intensity; }
262
263 protected:
264 float intensity_{};
265 float alpha_{};
266};
267
268} // namespace esphome::light
Lightweight read-only view over a const array stored in RODATA (will typically be in flash memory).
Definition helpers.h:130
void stop_action()
Stop any action connected to this trigger.
Definition automation.h:564
bool is_action_running()
Returns true if any action connected to this trigger is running.
Definition automation.h:570
void trigger(const Ts &...x) ESPHOME_ALWAYS_INLINE
Inform the parent automation that the event has triggered.
Definition automation.h:556
uint32_t get_current_index() const
Get the current effect index for use in automations.
uint32_t get_current_index() const
Get the current effect index for use in lambda functions.
LambdaLightEffect(const char *name, void(*f)(LightState &, bool initial_run), uint32_t update_interval)
void(* f_)(LightState &, bool initial_run)
LightCall & set_publish(bool publish)
Set whether this light call should trigger a publish state.
LightCall & set_transition_length_if_supported(uint32_t transition_length)
Set the transition length property if the light supports transitions.
LightCall & set_save(bool save)
Set whether this light call should trigger a save state to recover them at startup....
LightCall & from_light_color_values(const LightColorValues &values)
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_cold_white() const
Get the cold white property of these light color values. In range 0.0 to 1.0.
void set_blue(float blue)
Set the blue property of these light color values. In range 0.0 to 1.0.
void set_cold_white(float cold_white)
Set the cold white property of these light color values. In range 0.0 to 1.0.
void set_warm_white(float warm_white)
Set the warm 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.
void set_white(float white)
Set the white property of these light color values. In range 0.0 to 1.0.
float get_red() const
Get the red property of these light color values. In range 0.0 to 1.0.
void set_green(float green)
Set the green property of these light color values. In range 0.0 to 1.0.
void set_red(float red)
Set the red property of these light color values. In range 0.0 to 1.0.
uint32_t get_index() const
Get the index of this effect in the parent light's effect list.
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
Definition light_state.h:68
LightColorValues remote_values
The remote color values reported to the frontend.
LightCall turn_on()
Make a light state call.
LightColorValues current_values
The current values of the light as outputted to the light.
void set_min_max_brightness(float min, float max)
void set_update_interval(uint32_t update_interval)
void set_transition_off_length(uint32_t transition_length)
void set_transition_on_length(uint32_t transition_length)
Random effect. Sets random colors every 10 seconds and slowly transitions between them.
void set_update_interval(uint32_t update_interval)
void set_transition_length(uint32_t transition_length)
uint32_t duration_(size_t index) const
void set_colors(const StrobeLightEffectColor *colors, size_t count)
Codegen only: point at the generated flash table of steps, which must outlive the effect.
ConstVector< StrobeLightEffectColor > colors_
std::vector< uint8_t > & out
Definition gif.cpp:49
unsigned count
Definition gif.cpp:51
uint8_t duration
Definition msa3xx.h:0
ColorMode
Color modes are a combination of color capabilities that can be used at the same time.
Definition color_mode.h:50
@ RGB
Color can be controlled using RGB format (includes a brightness control for the color).
@ COLOR_TEMPERATURE
Color temperature can be controlled.
@ COLD_WARM_WHITE
Brightness of cold and warm white output can be controlled.
float random_float()
Return a random float between 0 and 1.
Definition helpers.cpp:206
void progmem_memcpy(void *dst, const void *src, size_t len)
Definition hal.h:56
uint32_t IRAM_ATTR HOT millis()
Definition hal.cpp:25
One strobe step. Codegen keeps the steps in a flash table, so it is read with progmem_memcpy.