ESPHome 2025.5.0
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 {
8namespace light {
9
10enum class LimitMode { CLAMP, DO_NOTHING };
11
12template<typename... Ts> class ToggleAction : public Action<Ts...> {
13 public:
15
16 TEMPLATABLE_VALUE(uint32_t, transition_length)
17
18 void play(Ts... x) override {
19 auto call = this->state_->toggle();
20 call.set_transition_length(this->transition_length_.optional_value(x...));
21 call.perform();
22 }
23
24 protected:
26};
27
28template<typename... Ts> class LightControlAction : public Action<Ts...> {
29 public:
30 explicit LightControlAction(LightState *parent) : parent_(parent) {}
31
34 TEMPLATABLE_VALUE(uint32_t, transition_length)
35 TEMPLATABLE_VALUE(uint32_t, flash_length)
36 TEMPLATABLE_VALUE(float, brightness)
37 TEMPLATABLE_VALUE(float, color_brightness)
39 TEMPLATABLE_VALUE(float, green)
40 TEMPLATABLE_VALUE(float, blue)
41 TEMPLATABLE_VALUE(float, white)
42 TEMPLATABLE_VALUE(float, color_temperature)
43 TEMPLATABLE_VALUE(float, cold_white)
44 TEMPLATABLE_VALUE(float, warm_white)
45 TEMPLATABLE_VALUE(std::string, effect)
46
47 void play(Ts... x) override {
48 auto call = this->parent_->make_call();
49 call.set_color_mode(this->color_mode_.optional_value(x...));
50 call.set_state(this->state_.optional_value(x...));
51 call.set_brightness(this->brightness_.optional_value(x...));
52 call.set_color_brightness(this->color_brightness_.optional_value(x...));
53 call.set_red(this->red_.optional_value(x...));
54 call.set_green(this->green_.optional_value(x...));
55 call.set_blue(this->blue_.optional_value(x...));
56 call.set_white(this->white_.optional_value(x...));
57 call.set_color_temperature(this->color_temperature_.optional_value(x...));
58 call.set_cold_white(this->cold_white_.optional_value(x...));
59 call.set_warm_white(this->warm_white_.optional_value(x...));
60 call.set_effect(this->effect_.optional_value(x...));
61 call.set_flash_length(this->flash_length_.optional_value(x...));
62 call.set_transition_length(this->transition_length_.optional_value(x...));
63 call.perform();
64 }
65
66 protected:
67 LightState *parent_;
68};
69
70template<typename... Ts> class DimRelativeAction : public Action<Ts...> {
71 public:
72 explicit DimRelativeAction(LightState *parent) : parent_(parent) {}
73
74 TEMPLATABLE_VALUE(float, relative_brightness)
75 TEMPLATABLE_VALUE(uint32_t, transition_length)
76
77 void play(Ts... x) override {
78 auto call = this->parent_->make_call();
79 float rel = this->relative_brightness_.value(x...);
80 float cur;
82 if ((limit_mode_ == LimitMode::DO_NOTHING) && ((cur < min_brightness_) || (cur > max_brightness_))) {
83 return;
84 }
85 float new_brightness = clamp(cur + rel, min_brightness_, max_brightness_);
86 call.set_state(new_brightness != 0.0f);
87 call.set_brightness(new_brightness);
88
89 call.set_transition_length(this->transition_length_.optional_value(x...));
90 call.perform();
91 }
92
93 void set_min_max_brightness(float min, float max) {
94 this->min_brightness_ = min;
95 this->max_brightness_ = max;
96 }
97
98 void set_limit_mode(LimitMode limit_mode) { this->limit_mode_ = limit_mode; }
99
100 protected:
102 float min_brightness_{0.0};
103 float max_brightness_{1.0};
105};
106
107template<typename... Ts> class LightIsOnCondition : public Condition<Ts...> {
108 public:
110 bool check(Ts... x) override { return this->state_->current_values.is_on(); }
111
112 protected:
114};
115template<typename... Ts> class LightIsOffCondition : public Condition<Ts...> {
116 public:
118 bool check(Ts... x) override { return !this->state_->current_values.is_on(); }
119
120 protected:
122};
123
124class LightTurnOnTrigger : public Trigger<> {
125 public:
127 a_light->add_new_remote_values_callback([this, a_light]() {
128 // using the remote value because of transitions we need to trigger as early as possible
129 auto is_on = a_light->remote_values.is_on();
130 // only trigger when going from off to on
131 auto should_trigger = is_on && !this->last_on_;
132 // Set new state immediately so that trigger() doesn't devolve
133 // into infinite loop
134 this->last_on_ = is_on;
135 if (should_trigger) {
136 this->trigger();
137 }
138 });
139 this->last_on_ = a_light->current_values.is_on();
140 }
141
142 protected:
144};
145
146class LightTurnOffTrigger : public Trigger<> {
147 public:
149 a_light->add_new_target_state_reached_callback([this, a_light]() {
150 auto is_on = a_light->current_values.is_on();
151 // only trigger when going from on to off
152 if (!is_on) {
153 this->trigger();
154 }
155 });
156 }
157};
158
159class LightStateTrigger : public Trigger<> {
160 public:
162 a_light->add_new_remote_values_callback([this]() { this->trigger(); });
163 }
164};
165
166// This is slightly ugly, but we can't log in headers, and can't make this a static method on AddressableSet
167// due to the template. It's just a temporary warning anyway.
168void addressableset_warn_about_scale(const char *field);
169
170template<typename... Ts> class AddressableSet : public Action<Ts...> {
171 public:
172 explicit AddressableSet(LightState *parent) : parent_(parent) {}
173
174 TEMPLATABLE_VALUE(int32_t, range_from)
175 TEMPLATABLE_VALUE(int32_t, range_to)
176 TEMPLATABLE_VALUE(float, color_brightness)
177 TEMPLATABLE_VALUE(float, red)
178 TEMPLATABLE_VALUE(float, green)
179 TEMPLATABLE_VALUE(float, blue)
180 TEMPLATABLE_VALUE(float, white)
181
182 void play(Ts... x) override {
183 auto *out = (AddressableLight *) this->parent_->get_output();
184 int32_t range_from = interpret_index(this->range_from_.value_or(x..., 0), out->size());
185 if (range_from < 0 || range_from >= out->size())
186 range_from = 0;
187
188 int32_t range_to = interpret_index(this->range_to_.value_or(x..., out->size() - 1) + 1, out->size());
189 if (range_to < 0 || range_to >= out->size())
190 range_to = out->size();
191
192 uint8_t color_brightness =
193 to_uint8_scale(this->color_brightness_.value_or(x..., this->parent_->remote_values.get_color_brightness()));
194 auto range = out->range(range_from, range_to);
195 if (this->red_.has_value())
196 range.set_red(esp_scale8(to_uint8_compat(this->red_.value(x...), "red"), color_brightness));
197 if (this->green_.has_value())
198 range.set_green(esp_scale8(to_uint8_compat(this->green_.value(x...), "green"), color_brightness));
199 if (this->blue_.has_value())
200 range.set_blue(esp_scale8(to_uint8_compat(this->blue_.value(x...), "blue"), color_brightness));
201 if (this->white_.has_value())
202 range.set_white(to_uint8_compat(this->white_.value(x...), "white"));
203 out->schedule_show();
204 }
205
206 protected:
208
209 // Historically, this action required uint8_t (0-255) for RGBW values from lambdas. Keep compatibility.
210 static inline uint8_t to_uint8_compat(float value, const char *field) {
211 if (value > 1.0f) {
213 return static_cast<uint8_t>(value);
214 }
215 return to_uint8_scale(value);
216 }
217};
218
219} // namespace light
220} // namespace esphome
virtual void play(Ts... x)=0
Base class for all automation conditions.
Definition automation.h:75
void trigger(Ts... x)
Definition automation.h:96
static uint8_t to_uint8_compat(float value, const char *field)
Definition automation.h:210
AddressableSet(LightState *parent)
Definition automation.h:172
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:72
void set_min_max_brightness(float min, float max)
Definition automation.h:93
transition_length void play(Ts... x) override
Definition automation.h:77
void set_limit_mode(LimitMode limit_mode)
Definition automation.h:98
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, float gamma=0) const
Convert these light color values to a brightness-only representation and write them to brightness.
TEMPLATABLE_VALUE(ColorMode, color_mode) TEMPLATABLE_VALUE(bool
LightControlAction(LightState *parent)
Definition automation.h:30
bool check(Ts... x) override
Definition automation.h:118
LightIsOffCondition(LightState *state)
Definition automation.h:117
LightIsOnCondition(LightState *state)
Definition automation.h:109
bool check(Ts... x) override
Definition automation.h:110
This class represents the communication layer between the front-end MQTT layer and the hardware outpu...
Definition light_state.h:63
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_new_remote_values_callback(std::function< void()> &&send_callback)
This lets front-end components subscribe to light change events.
void add_new_target_state_reached_callback(std::function< void()> &&send_callback)
The callback is called once the state of current_values and remote_values are equal (when the transit...
LightColorValues current_values
The current values of the light as outputted to the light.
Definition light_state.h:94
LightStateTrigger(LightState *a_light)
Definition automation.h:161
LightTurnOffTrigger(LightState *a_light)
Definition automation.h:148
LightTurnOnTrigger(LightState *a_light)
Definition automation.h:126
TEMPLATABLE_VALUE(uint32_t, transition_length) void play(Ts... x) override
Definition automation.h:16
ToggleAction(LightState *state)
Definition automation.h:14
bool state
Definition fan.h:0
Range range
Definition msa3xx.h:0
void addressableset_warn_about_scale(const char *field)
Definition automation.cpp:9
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)
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
constexpr const T & clamp(const T &v, const T &lo, const T &hi, Compare comp)
Definition helpers.h:101
uint16_t x
Definition tt21100.cpp:5