ESPHome 2025.5.0
Loading...
Searching...
No Matches
time_based_cover.cpp
Go to the documentation of this file.
1#include "time_based_cover.h"
2#include "esphome/core/log.h"
3#include "esphome/core/hal.h"
5
6namespace esphome {
7namespace time_based {
8
9static const char *const TAG = "time_based.cover";
10
11using namespace esphome::cover;
12
14 LOG_COVER("", "Time Based Cover", this);
15 ESP_LOGCONFIG(TAG, " Open Duration: %.1fs", this->open_duration_ / 1e3f);
16 ESP_LOGCONFIG(TAG, " Close Duration: %.1fs", this->close_duration_ / 1e3f);
17}
19 auto restore = this->restore_state_();
20 if (restore.has_value()) {
21 restore->apply(this);
22 } else {
23 this->position = 0.5f;
24 }
25}
28 return;
29
30 const uint32_t now = App.get_loop_component_start_time();
31
32 // Recompute position every loop cycle
33 this->recompute_position_();
34
35 if (this->is_at_target_()) {
36 if (this->has_built_in_endstop_ &&
38 // Don't trigger stop, let the cover stop by itself.
40 } else {
42 }
43 this->publish_state();
44 }
45
46 // Send current position every second
47 if (now - this->last_publish_time_ > 1000) {
48 this->publish_state(false);
49 this->last_publish_time_ = now;
50 }
51}
54 auto traits = CoverTraits();
55 traits.set_supports_stop(true);
56 traits.set_supports_position(true);
57 traits.set_supports_toggle(true);
58 traits.set_is_assumed_state(this->assumed_state_);
59 return traits;
60}
62 if (call.get_stop()) {
64 this->publish_state();
65 }
66 if (call.get_toggle().has_value()) {
69 this->publish_state();
70 } else {
74 } else {
77 }
78 }
79 }
80 if (call.get_position().has_value()) {
81 auto pos = *call.get_position();
82 if (pos == this->position) {
83 // already at target
84 if (this->manual_control_ && (pos == COVER_OPEN || pos == COVER_CLOSED)) {
85 // for covers with manual control switch, we can't rely on the computed position, so if
86 // the command triggered again, we'll assume it's in the opposite direction anyway.
89 this->target_position_ = pos;
90 this->start_direction_(op);
91 }
92 // for covers with built in end stop, we should send the command again
93 if (this->has_built_in_endstop_ && (pos == COVER_OPEN || pos == COVER_CLOSED)) {
95 this->target_position_ = pos;
96 this->start_direction_(op);
97 }
98 } else {
100 if (this->manual_control_ && (pos == COVER_OPEN || pos == COVER_CLOSED)) {
101 this->position = pos == COVER_CLOSED ? COVER_OPEN : COVER_CLOSED;
102 }
103 this->target_position_ = pos;
104 this->start_direction_(op);
105 }
106 }
107}
109 if (this->prev_command_trigger_ != nullptr) {
111 this->prev_command_trigger_ = nullptr;
112 }
113}
115 switch (this->current_operation) {
117 return this->position >= this->target_position_;
119 return this->position <= this->target_position_;
121 default:
122 return true;
123 }
124}
126 if (dir == this->current_operation && dir != COVER_OPERATION_IDLE)
127 return;
128
129 this->recompute_position_();
130 Trigger<> *trig;
131 switch (dir) {
133 trig = this->stop_trigger_;
134 break;
136 this->last_operation_ = dir;
137 trig = this->open_trigger_;
138 break;
140 this->last_operation_ = dir;
141 trig = this->close_trigger_;
142 break;
143 default:
144 return;
145 }
146
147 this->current_operation = dir;
148
149 const uint32_t now = millis();
150 this->start_dir_time_ = now;
151 this->last_recompute_time_ = now;
152
153 this->stop_prev_trigger_();
154 trig->trigger();
155 this->prev_command_trigger_ = trig;
156}
159 return;
160
161 float dir;
162 float action_dur;
163 switch (this->current_operation) {
165 dir = 1.0f;
166 action_dur = this->open_duration_;
167 break;
169 dir = -1.0f;
170 action_dur = this->close_duration_;
171 break;
172 default:
173 return;
174 }
175
176 const uint32_t now = millis();
177 this->position += dir * (now - this->last_recompute_time_) / action_dur;
178 this->position = clamp(this->position, 0.0f, 1.0f);
179
180 this->last_recompute_time_ = now;
181}
182
183} // namespace time_based
184} // namespace esphome
uint32_t IRAM_ATTR HOT get_loop_component_start_time() const
Get the cached time in milliseconds from when the current component started its loop execution.
void stop_action()
Stop any action connected to this trigger.
Definition automation.h:104
void trigger(Ts... x)
Inform the parent automation that the event has triggered.
Definition automation.h:96
const optional< bool > & get_toggle() const
Definition cover.cpp:99
const optional< float > & get_position() const
Definition cover.cpp:97
CoverOperation current_operation
The current operation of the cover (idle, opening, closing).
Definition cover.h:116
optional< CoverRestoreState > restore_state_()
Definition cover.cpp:200
void publish_state(bool save=true)
Publish the current state of the cover.
Definition cover.cpp:166
float position
The position of the cover from 0.0 (fully closed) to 1.0 (fully open).
Definition cover.h:122
bool has_value() const
Definition optional.h:87
cover::CoverTraits get_traits() override
float get_setup_priority() const override
void start_direction_(cover::CoverOperation dir)
void control(const cover::CoverCall &call) override
const float COVER_CLOSED
Definition cover.cpp:10
const float COVER_OPEN
Definition cover.cpp:9
CoverOperation
Enum encoding the current operation of a cover.
Definition cover.h:80
@ COVER_OPERATION_OPENING
The cover is currently opening.
Definition cover.h:84
@ COVER_OPERATION_CLOSING
The cover is currently closing.
Definition cover.h:86
@ COVER_OPERATION_IDLE
The cover is currently idle (not moving)
Definition cover.h:82
const float DATA
For components that import data from directly connected sensors like DHT.
Definition component.cpp:19
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
uint32_t IRAM_ATTR HOT millis()
Definition core.cpp:27
Application App
Global storage of Application pointer - only one Application can exist.
constexpr const T & clamp(const T &v, const T &lo, const T &hi, Compare comp)
Definition helpers.h:101