ESPHome 2026.5.0
Loading...
Searching...
No Matches
automation.h
Go to the documentation of this file.
1#pragma once
2
5#include "fan.h"
6
7namespace esphome::fan {
8
9// All configured fields are baked into a single stateless lambda whose
10// constants live in flash. The action only stores one function pointer
11// plus one parent pointer, regardless of how many fields the user set.
12// Trigger args are forwarded to the apply function so user lambdas
13// (e.g. `speed: !lambda "return x;"`) keep working.
14//
15// Trigger args are normalized to `const std::remove_cvref_t<Ts> &...` so
16// the codegen can emit a matching parameter list for both the apply lambda
17// and any inner field lambdas without producing invalid C++ source text
18// (e.g. `const T & &` if Ts already carries a reference, or `const const
19// T &` if Ts already carries a const). This keeps trigger args no-copy
20// regardless of whether the trigger supplies `T`, `T &`, or `const T &`.
21template<typename... Ts> class TurnOnAction : public Action<Ts...> {
22 public:
23 using ApplyFn = void (*)(FanCall &, const std::remove_cvref_t<Ts> &...);
25
26 void play(const Ts &...x) override {
27 auto call = this->state_->turn_on();
28 this->apply_(call, x...);
29 call.perform();
30 }
31
34};
35
36template<typename... Ts> class TurnOffAction : public Action<Ts...> {
37 public:
39
40 void play(const Ts &...x) override { this->state_->turn_off().perform(); }
41
43};
44
45template<typename... Ts> class ToggleAction : public Action<Ts...> {
46 public:
48
49 void play(const Ts &...x) override { this->state_->toggle().perform(); }
50
52};
53
54template<typename... Ts> class CycleSpeedAction : public Action<Ts...> {
55 public:
57
58 TEMPLATABLE_VALUE(bool, no_off_cycle)
59
60 void play(const Ts &...x) override {
61 // check to see if fan supports speeds and is on
63 if (this->state_->state) {
64 int speed = this->state_->speed + 1;
65 int supported_speed_count = this->state_->get_traits().supported_speed_count();
66 bool off_speed_cycle = no_off_cycle_.value(x...);
67 if (speed > supported_speed_count && off_speed_cycle) {
68 // was running at max speed, off speed cycle enabled, so turn off
69 speed = 1;
70 auto call = this->state_->turn_off();
71 call.set_speed(speed);
72 call.perform();
73 } else if (speed > supported_speed_count && !off_speed_cycle) {
74 // was running at max speed, off speed cycle disabled, so set to lowest speed
75 auto call = this->state_->turn_on();
76 call.set_speed(1);
77 call.perform();
78 } else {
79 auto call = this->state_->turn_on();
80 call.set_speed(speed);
81 call.perform();
82 }
83 } else {
84 // fan was off, so set speed to 1
85 auto call = this->state_->turn_on();
86 call.set_speed(1);
87 call.perform();
88 }
89 } else {
90 // fan doesn't support speed counts, so toggle
91 this->state_->toggle().perform();
92 }
93 }
94
96};
97
98template<typename... Ts> class FanIsOnCondition : public Condition<Ts...> {
99 public:
101 bool check(const Ts &...x) override { return this->state_->state; }
102
103 protected:
105};
106template<typename... Ts> class FanIsOffCondition : public Condition<Ts...> {
107 public:
109 bool check(const Ts &...x) override { return !this->state_->state; }
110
111 protected:
113};
114
115class FanStateTrigger : public Trigger<Fan *> {
116 public:
118 state->add_on_state_callback([this]() { this->trigger(this->fan_); });
119 }
120
121 protected:
123};
124
125class FanTurnOnTrigger : public Trigger<> {
126 public:
128 state->add_on_state_callback([this]() {
129 auto is_on = this->fan_->state;
130 auto should_trigger = is_on && !this->last_on_;
131 this->last_on_ = is_on;
132 if (should_trigger) {
133 this->trigger();
134 }
135 });
136 this->last_on_ = state->state;
137 }
138
139 protected:
142};
143
144class FanTurnOffTrigger : public Trigger<> {
145 public:
147 state->add_on_state_callback([this]() {
148 auto is_on = this->fan_->state;
149 auto should_trigger = !is_on && this->last_on_;
150 this->last_on_ = is_on;
151 if (should_trigger) {
152 this->trigger();
153 }
154 });
155 this->last_on_ = state->state;
156 }
157
158 protected:
161};
162
163class FanDirectionSetTrigger : public Trigger<FanDirection> {
164 public:
166 state->add_on_state_callback([this]() {
167 auto direction = this->fan_->direction;
168 auto should_trigger = direction != this->last_direction_;
170 if (should_trigger) {
171 this->trigger(direction);
172 }
173 });
174 this->last_direction_ = state->direction;
175 }
176
177 protected:
180};
181
182class FanOscillatingSetTrigger : public Trigger<bool> {
183 public:
185 state->add_on_state_callback([this]() {
186 auto oscillating = this->fan_->oscillating;
187 auto should_trigger = oscillating != this->last_oscillating_;
189 if (should_trigger) {
190 this->trigger(oscillating);
191 }
192 });
193 this->last_oscillating_ = state->oscillating;
194 }
195
196 protected:
199};
200
201class FanSpeedSetTrigger : public Trigger<int> {
202 public:
204 state->add_on_state_callback([this]() {
205 auto speed = this->fan_->speed;
206 auto should_trigger = speed != this->last_speed_;
207 this->last_speed_ = speed;
208 if (should_trigger) {
209 this->trigger(speed);
210 }
211 });
212 this->last_speed_ = state->speed;
213 }
214
215 protected:
218};
219
220class FanPresetSetTrigger : public Trigger<StringRef> {
221 public:
223 state->add_on_state_callback([this]() {
224 auto preset_mode = this->fan_->get_preset_mode();
225 auto should_trigger = preset_mode != this->last_preset_mode_;
227 if (should_trigger) {
228 this->trigger(preset_mode);
229 }
230 });
231 this->last_preset_mode_ = state->get_preset_mode();
232 }
233
234 protected:
237};
238
239} // namespace esphome::fan
virtual void play(const Ts &...x)=0
Base class for all automation conditions.
Definition automation.h:459
StringRef is a reference to a string owned by something else.
Definition string_ref.h:26
void trigger(const Ts &...x) ESPHOME_ALWAYS_INLINE
Definition automation.h:482
TEMPLATABLE_VALUE(bool, no_off_cycle) void play(const Ts &...x) override
Definition automation.h:58
FanCall & set_speed(int speed)
Definition fan.h:59
void add_on_state_callback(F &&callback)
Register a callback that will be called each time the state changes.
Definition fan.h:124
FanCall turn_on()
Definition fan.cpp:156
FanCall turn_off()
Definition fan.cpp:157
virtual FanTraits get_traits()=0
FanCall toggle()
Definition fan.cpp:158
StringRef get_preset_mode() const
Get the current preset mode.
Definition fan.h:147
FanDirection direction
The current direction of the fan.
Definition fan.h:116
bool oscillating
The current oscillation state of the fan.
Definition fan.h:112
bool state
The current on/off state of the fan.
Definition fan.h:110
int speed
The current fan speed level.
Definition fan.h:114
bool check(const Ts &...x) override
Definition automation.h:109
bool check(const Ts &...x) override
Definition automation.h:101
int supported_speed_count() const
Return how many speed levels the fan has.
Definition fan_traits.h:29
void play(const Ts &...x) override
Definition automation.h:49
void play(const Ts &...x) override
Definition automation.h:40
TurnOnAction(Fan *state, ApplyFn apply)
Definition automation.h:24
void(*)(FanCall &, const std::remove_cvref_t< Ts > &...) ApplyFn
Definition automation.h:23
void play(const Ts &...x) override
Definition automation.h:26
void apply(Climate *climate)
Apply these settings to the climate device.
FanDirection direction
Definition fan.h:5
int speed
Definition fan.h:3
bool oscillating
Definition fan.h:4
uint8_t preset_mode
Definition fan.h:6
bool state
Definition fan.h:2
FanDirection
Simple enum to represent the direction of a fan.
Definition fan.h:20
uint16_t x
Definition tt21100.cpp:5