ESPHome 2026.5.0-dev
Loading...
Searching...
No Matches
automation.h
Go to the documentation of this file.
1#pragma once
2
4#include "light_state.h"
5#include "addressable_light.h"
6
7namespace esphome::light {
8
9enum class LimitMode { CLAMP, DO_NOTHING };
10
11template<typename... Ts> class ToggleAction : public Action<Ts...> {
12 public:
14
15 TEMPLATABLE_VALUE(uint32_t, transition_length)
16
17 void play(const Ts &...x) override {
18 auto call = this->state_->toggle();
19 call.set_transition_length(this->transition_length_.optional_value(x...));
20 call.perform();
21 }
22
23 protected:
25};
26
27template<typename... Ts> class LightControlAction : public Action<Ts...> {
28 public:
29 explicit LightControlAction(LightState *parent) : parent_(parent) {}
30
33 TEMPLATABLE_VALUE(uint32_t, transition_length)
34 TEMPLATABLE_VALUE(uint32_t, flash_length)
35 TEMPLATABLE_VALUE(float, brightness)
36 TEMPLATABLE_VALUE(float, color_brightness)
38 TEMPLATABLE_VALUE(float, green)
39 TEMPLATABLE_VALUE(float, blue)
40 TEMPLATABLE_VALUE(float, white)
41 TEMPLATABLE_VALUE(float, color_temperature)
42 TEMPLATABLE_VALUE(float, cold_white)
43 TEMPLATABLE_VALUE(float, warm_white)
45
46 void play(const Ts &...x) override {
47 auto call = this->parent_->make_call();
48 if (this->color_mode_.has_value())
49 call.set_color_mode(this->color_mode_.value(x...));
50 if (this->state_.has_value())
51 call.set_state(this->state_.value(x...));
52 if (this->transition_length_.has_value())
53 call.set_transition_length(this->transition_length_.value(x...));
54 if (this->flash_length_.has_value())
55 call.set_flash_length(this->flash_length_.value(x...));
56 if (this->brightness_.has_value())
57 call.set_brightness(this->brightness_.value(x...));
58 if (this->color_brightness_.has_value())
59 call.set_color_brightness(this->color_brightness_.value(x...));
60 if (this->red_.has_value())
61 call.set_red(this->red_.value(x...));
62 if (this->green_.has_value())
63 call.set_green(this->green_.value(x...));
64 if (this->blue_.has_value())
65 call.set_blue(this->blue_.value(x...));
66 if (this->white_.has_value())
67 call.set_white(this->white_.value(x...));
68 if (this->color_temperature_.has_value())
69 call.set_color_temperature(this->color_temperature_.value(x...));
70 if (this->cold_white_.has_value())
71 call.set_cold_white(this->cold_white_.value(x...));
72 if (this->warm_white_.has_value())
73 call.set_warm_white(this->warm_white_.value(x...));
74 if (this->effect_.has_value())
75 call.set_effect(this->effect_.value(x...));
76 call.perform();
77 }
78
79 protected:
81};
82
83template<typename... Ts> class DimRelativeAction : public Action<Ts...> {
84 public:
85 explicit DimRelativeAction(LightState *parent) : parent_(parent) {}
86
87 TEMPLATABLE_VALUE(float, relative_brightness)
88 TEMPLATABLE_VALUE(uint32_t, transition_length)
89
90 void play(const Ts &...x) override {
91 auto call = this->parent_->make_call();
92 float rel = this->relative_brightness_.value(x...);
93 float cur;
96 return;
97 }
98 float new_brightness = clamp(cur + rel, min_brightness_, max_brightness_);
99 call.set_state(new_brightness != 0.0f);
100 call.set_brightness(new_brightness);
101
102 call.set_transition_length(this->transition_length_.optional_value(x...));
103 call.perform();
104 }
105
106 void set_min_max_brightness(float min, float max) {
107 this->min_brightness_ = min;
108 this->max_brightness_ = max;
109 }
110
111 void set_limit_mode(LimitMode limit_mode) { this->limit_mode_ = limit_mode; }
112
113 protected:
115 float min_brightness_{0.0};
116 float max_brightness_{1.0};
118};
119
120template<typename... Ts> class LightIsOnCondition : public Condition<Ts...> {
121 public:
123 bool check(const Ts &...x) override { return this->state_->current_values.is_on(); }
124
125 protected:
127};
128template<typename... Ts> class LightIsOffCondition : public Condition<Ts...> {
129 public:
131 bool check(const Ts &...x) override { return !this->state_->current_values.is_on(); }
132
133 protected:
135};
136
138 public:
139 explicit LightTurnOnTrigger(LightState *a_light) : light_(a_light) {
140 a_light->add_remote_values_listener(this);
141 this->last_on_ = a_light->current_values.is_on();
142 }
143
145 // using the remote value because of transitions we need to trigger as early as possible
146 auto is_on = this->light_->remote_values.is_on();
147 // only trigger when going from off to on
148 auto should_trigger = is_on && !this->last_on_;
149 // Set new state immediately so that trigger() doesn't devolve
150 // into infinite loop
151 this->last_on_ = is_on;
152 if (should_trigger) {
153 this->trigger();
154 }
155 }
156
157 protected:
160};
161
163 public:
164 explicit LightTurnOffTrigger(LightState *a_light) : light_(a_light) {
166 }
167
169 auto is_on = this->light_->current_values.is_on();
170 // only trigger when going from on to off
171 if (!is_on) {
172 this->trigger();
173 }
174 }
175
176 protected:
178};
179
181 public:
182 explicit LightStateTrigger(LightState *a_light) { a_light->add_remote_values_listener(this); }
183
184 void on_light_remote_values_update() override { this->trigger(); }
185};
186
187// This is slightly ugly, but we can't log in headers, and can't make this a static method on AddressableSet
188// due to the template. It's just a temporary warning anyway.
189void addressableset_warn_about_scale(const char *field);
190
191template<typename... Ts> class AddressableSet : public Action<Ts...> {
192 public:
193 explicit AddressableSet(LightState *parent) : parent_(parent) {}
194
195 TEMPLATABLE_VALUE(int32_t, range_from)
196 TEMPLATABLE_VALUE(int32_t, range_to)
197 TEMPLATABLE_VALUE(float, color_brightness)
198 TEMPLATABLE_VALUE(float, red)
199 TEMPLATABLE_VALUE(float, green)
200 TEMPLATABLE_VALUE(float, blue)
201 TEMPLATABLE_VALUE(float, white)
202
203 void play(const Ts &...x) override {
204 auto *out = (AddressableLight *) this->parent_->get_output();
205 int32_t range_from = interpret_index(this->range_from_.value_or(x..., 0), out->size());
206 if (range_from < 0 || range_from >= out->size())
207 range_from = 0;
208
209 int32_t range_to = interpret_index(this->range_to_.value_or(x..., out->size() - 1) + 1, out->size());
210 if (range_to < 0 || range_to >= out->size())
211 range_to = out->size();
212
213 uint8_t color_brightness =
214 to_uint8_scale(this->color_brightness_.value_or(x..., this->parent_->remote_values.get_color_brightness()));
215 auto range = out->range(range_from, range_to);
216 if (this->red_.has_value())
217 range.set_red(esp_scale8(to_uint8_compat(this->red_.value(x...), "red"), color_brightness));
218 if (this->green_.has_value())
219 range.set_green(esp_scale8(to_uint8_compat(this->green_.value(x...), "green"), color_brightness));
220 if (this->blue_.has_value())
221 range.set_blue(esp_scale8(to_uint8_compat(this->blue_.value(x...), "blue"), color_brightness));
222 if (this->white_.has_value())
223 range.set_white(to_uint8_compat(this->white_.value(x...), "white"));
224 out->schedule_show();
225 }
226
227 protected:
229
230 // Historically, this action required uint8_t (0-255) for RGBW values from lambdas. Keep compatibility.
231 static inline uint8_t to_uint8_compat(float value, const char *field) {
232 if (value > 1.0f) {
234 return static_cast<uint8_t>(value);
235 }
236 return to_uint8_scale(value);
237 }
238};
239
240} // namespace esphome::light
virtual void play(const Ts &...x)=0
Base class for all automation conditions.
Definition automation.h:459
void trigger(const Ts &...x) ESPHOME_ALWAYS_INLINE
Definition automation.h:482
static uint8_t to_uint8_compat(float value, const char *field)
Definition automation.h:231
AddressableSet(LightState *parent)
Definition automation.h:193
TEMPLATABLE_VALUE(int32_t, range_from) TEMPLATABLE_VALUE(int32_t
TEMPLATABLE_VALUE(float, relative_brightness) TEMPLATABLE_VALUE(uint32_t
DimRelativeAction(LightState *parent)
Definition automation.h:85
void set_min_max_brightness(float min, float max)
Definition automation.h:106
void set_limit_mode(LimitMode limit_mode)
Definition automation.h:111
transition_length void play(const Ts &...x) override
Definition automation.h:90
LightCall & set_color_temperature(optional< float > color_temperature)
Set the color temperature of the light in mireds for CWWW or RGBWW lights.
LightCall & set_color_brightness(optional< float > brightness)
Set the color brightness of the light from 0.0 (no color) to 1.0 (fully on)
LightCall & set_effect(optional< std::string > effect)
Set the effect of the light by its name.
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_warm_white(optional< float > warm_white)
Set the warm white value of the light from 0.0 to 1.0.
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.
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_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.
LightCall & set_transition_length(optional< uint32_t > transition_length)
Set the transition length of this call in milliseconds.
bool is_on() const
Get the binary true/false state of these light color values.
void as_brightness(float *brightness) const
Convert these light color values to a brightness-only representation and write them to brightness.
state flash_length color_brightness green white cold_white effect void play(const Ts &...x) override
Definition automation.h:46
TEMPLATABLE_VALUE(ColorMode, color_mode) TEMPLATABLE_VALUE(bool
LightControlAction(LightState *parent)
Definition automation.h:29
bool check(const Ts &...x) override
Definition automation.h:131
LightIsOffCondition(LightState *state)
Definition automation.h:130
LightIsOnCondition(LightState *state)
Definition automation.h:122
bool check(const Ts &...x) override
Definition automation.h:123
Listener interface for light remote value changes.
Definition light_state.h:31
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
Definition light_state.h:93
void add_remote_values_listener(LightRemoteValuesListener *listener)
Add a listener for remote values changes.
LightColorValues remote_values
The remote color values reported to the frontend.
LightOutput * get_output() const
Get the light output associated with this object.
void add_target_state_reached_listener(LightTargetStateReachedListener *listener)
Add a listener for target state reached.
LightColorValues current_values
The current values of the light as outputted to the light.
void on_light_remote_values_update() override
Definition automation.h:184
LightStateTrigger(LightState *a_light)
Definition automation.h:182
Listener interface for light target state reached.
Definition light_state.h:42
void on_light_target_state_reached() override
Definition automation.h:168
LightTurnOffTrigger(LightState *a_light)
Definition automation.h:164
LightTurnOnTrigger(LightState *a_light)
Definition automation.h:139
void on_light_remote_values_update() override
Definition automation.h:144
TEMPLATABLE_VALUE(uint32_t, transition_length) void play(const Ts &...x) override
Definition automation.h:15
ToggleAction(LightState *state)
Definition automation.h:13
bool state
Definition fan.h:2
Range range
Definition msa3xx.h:0
void addressableset_warn_about_scale(const char *field)
Definition automation.cpp:8
ColorMode
Color modes are a combination of color capabilities that can be used at the same time.
Definition color_mode.h:49
int32_t HOT interpret_index(int32_t index, int32_t size)
if(written< 0)
Definition helpers.h:1091
uint16_t x
Definition tt21100.cpp:5