ESPHome 2025.10.0-dev
Loading...
Searching...
No Matches
cover.cpp
Go to the documentation of this file.
1#include "cover.h"
2#include "esphome/core/log.h"
3#include <strings.h>
4
5namespace esphome {
6namespace cover {
7
8static const char *const TAG = "cover";
9
10const float COVER_OPEN = 1.0f;
11const float COVER_CLOSED = 0.0f;
12
13const char *cover_command_to_str(float pos) {
14 if (pos == COVER_OPEN) {
15 return "OPEN";
16 } else if (pos == COVER_CLOSED) {
17 return "CLOSE";
18 } else {
19 return "UNKNOWN";
20 }
21}
23 switch (op) {
25 return "IDLE";
27 return "OPENING";
29 return "CLOSING";
30 default:
31 return "UNKNOWN";
32 }
33}
34
36
37CoverCall::CoverCall(Cover *parent) : parent_(parent) {}
38CoverCall &CoverCall::set_command(const char *command) {
39 if (strcasecmp(command, "OPEN") == 0) {
40 this->set_command_open();
41 } else if (strcasecmp(command, "CLOSE") == 0) {
42 this->set_command_close();
43 } else if (strcasecmp(command, "STOP") == 0) {
44 this->set_command_stop();
45 } else if (strcasecmp(command, "TOGGLE") == 0) {
46 this->set_command_toggle();
47 } else {
48 ESP_LOGW(TAG, "'%s' - Unrecognized command %s", this->parent_->get_name().c_str(), command);
49 }
50 return *this;
51}
53 this->position_ = COVER_OPEN;
54 return *this;
55}
57 this->position_ = COVER_CLOSED;
58 return *this;
59}
61 this->stop_ = true;
62 return *this;
63}
65 this->toggle_ = true;
66 return *this;
67}
69 this->position_ = position;
70 return *this;
71}
73 this->tilt_ = tilt;
74 return *this;
75}
77 ESP_LOGD(TAG, "'%s' - Setting", this->parent_->get_name().c_str());
78 auto traits = this->parent_->get_traits();
79 this->validate_();
80 if (this->stop_) {
81 ESP_LOGD(TAG, " Command: STOP");
82 }
83 if (this->position_.has_value()) {
84 if (traits.get_supports_position()) {
85 ESP_LOGD(TAG, " Position: %.0f%%", *this->position_ * 100.0f);
86 } else {
87 ESP_LOGD(TAG, " Command: %s", cover_command_to_str(*this->position_));
88 }
89 }
90 if (this->tilt_.has_value()) {
91 ESP_LOGD(TAG, " Tilt: %.0f%%", *this->tilt_ * 100.0f);
92 }
93 if (this->toggle_.has_value()) {
94 ESP_LOGD(TAG, " Command: TOGGLE");
95 }
96 this->parent_->control(*this);
97}
98const optional<float> &CoverCall::get_position() const { return this->position_; }
99const optional<float> &CoverCall::get_tilt() const { return this->tilt_; }
100const optional<bool> &CoverCall::get_toggle() const { return this->toggle_; }
102 auto traits = this->parent_->get_traits();
103 const char *name = this->parent_->get_name().c_str();
104
105 if (this->position_.has_value()) {
106 auto pos = *this->position_;
107 if (!traits.get_supports_position() && pos != COVER_OPEN && pos != COVER_CLOSED) {
108 ESP_LOGW(TAG, "'%s': position unsupported", name);
109 this->position_.reset();
110 } else if (pos < 0.0f || pos > 1.0f) {
111 ESP_LOGW(TAG, "'%s': position %.2f out of range", name, pos);
112 this->position_ = clamp(pos, 0.0f, 1.0f);
113 }
114 }
115 if (this->tilt_.has_value()) {
116 auto tilt = *this->tilt_;
117 if (!traits.get_supports_tilt()) {
118 ESP_LOGW(TAG, "'%s': tilt unsupported", name);
119 this->tilt_.reset();
120 } else if (tilt < 0.0f || tilt > 1.0f) {
121 ESP_LOGW(TAG, "'%s': tilt %.2f out of range", name, tilt);
122 this->tilt_ = clamp(tilt, 0.0f, 1.0f);
123 }
124 }
125 if (this->toggle_.has_value()) {
126 if (!traits.get_supports_toggle()) {
127 ESP_LOGW(TAG, "'%s': toggle unsupported", name);
128 this->toggle_.reset();
129 }
130 }
131 if (this->stop_) {
132 if (this->position_.has_value() || this->tilt_.has_value() || this->toggle_.has_value()) {
133 ESP_LOGW(TAG, "'%s': cannot position/tilt/toggle when stopping", name);
134 this->position_.reset();
135 this->tilt_.reset();
136 this->toggle_.reset();
137 }
138 }
139}
141 this->stop_ = stop;
142 return *this;
143}
144bool CoverCall::get_stop() const { return this->stop_; }
145
146CoverCall Cover::make_call() { return {this}; }
147void Cover::open() {
148 auto call = this->make_call();
149 call.set_command_open();
150 call.perform();
151}
152void Cover::close() {
153 auto call = this->make_call();
154 call.set_command_close();
155 call.perform();
156}
157void Cover::stop() {
158 auto call = this->make_call();
159 call.set_command_stop();
160 call.perform();
161}
162void Cover::add_on_state_callback(std::function<void()> &&f) { this->state_callback_.add(std::move(f)); }
163void Cover::publish_state(bool save) {
164 this->position = clamp(this->position, 0.0f, 1.0f);
165 this->tilt = clamp(this->tilt, 0.0f, 1.0f);
166
167 ESP_LOGD(TAG, "'%s' - Publishing:", this->name_.c_str());
168 auto traits = this->get_traits();
169 if (traits.get_supports_position()) {
170 ESP_LOGD(TAG, " Position: %.0f%%", this->position * 100.0f);
171 } else {
172 if (this->position == COVER_OPEN) {
173 ESP_LOGD(TAG, " State: OPEN");
174 } else if (this->position == COVER_CLOSED) {
175 ESP_LOGD(TAG, " State: CLOSED");
176 } else {
177 ESP_LOGD(TAG, " State: UNKNOWN");
178 }
179 }
180 if (traits.get_supports_tilt()) {
181 ESP_LOGD(TAG, " Tilt: %.0f%%", this->tilt * 100.0f);
182 }
183 ESP_LOGD(TAG, " Current Operation: %s", cover_operation_to_str(this->current_operation));
184
185 this->state_callback_.call();
186
187 if (save) {
188 CoverRestoreState restore{};
189 memset(&restore, 0, sizeof(restore));
190 restore.position = this->position;
191 if (traits.get_supports_tilt()) {
192 restore.tilt = this->tilt;
193 }
194 this->rtc_.save(&restore);
195 }
196}
199 CoverRestoreState recovered{};
200 if (!this->rtc_.load(&recovered))
201 return {};
202 return recovered;
203}
204
205bool Cover::is_fully_open() const { return this->position == COVER_OPEN; }
206bool Cover::is_fully_closed() const { return this->position == COVER_CLOSED; }
207
209 auto call = cover->make_call();
210 auto traits = cover->get_traits();
211 call.set_position(this->position);
212 if (traits.get_supports_tilt())
213 call.set_tilt(this->tilt);
214 return call;
215}
217 cover->position = this->position;
218 cover->tilt = this->tilt;
219 cover->publish_state();
220}
221
222} // namespace cover
223} // namespace esphome
bool save(const T *src)
Definition preferences.h:21
virtual ESPPreferenceObject make_preference(size_t length, uint32_t type, bool in_flash)=0
const StringRef & get_name() const
uint32_t get_preference_hash()
Get a unique hash for storing preferences/settings for this entity.
constexpr const char * c_str() const
Definition string_ref.h:69
const optional< float > & get_tilt() const
Definition cover.cpp:99
CoverCall & set_command_toggle()
Set the command to toggle the cover.
Definition cover.cpp:64
const optional< bool > & get_toggle() const
Definition cover.cpp:100
optional< float > tilt_
Definition cover.h:64
CoverCall & set_command_open()
Set the command to open the cover.
Definition cover.cpp:52
CoverCall & set_command_close()
Set the command to close the cover.
Definition cover.cpp:56
CoverCall & set_command(const char *command)
Set the command as a string, "STOP", "OPEN", "CLOSE", "TOGGLE".
Definition cover.cpp:38
void perform()
Perform the cover call.
Definition cover.cpp:76
CoverCall & set_position(float position)
Set the call to a certain target position.
Definition cover.cpp:68
CoverCall & set_command_stop()
Set the command to stop the cover.
Definition cover.cpp:60
bool get_stop() const
Definition cover.cpp:144
optional< float > position_
Definition cover.h:63
const optional< float > & get_position() const
Definition cover.cpp:98
CoverCall(Cover *parent)
Definition cover.cpp:37
CoverCall & set_tilt(float tilt)
Set the call to a certain target tilt.
Definition cover.cpp:72
optional< bool > toggle_
Definition cover.h:65
CoverCall & set_stop(bool stop)
Set whether this cover call should stop the cover.
Definition cover.cpp:140
Base class for all cover devices.
Definition cover.h:111
CoverOperation current_operation
The current operation of the cover (idle, opening, closing).
Definition cover.h:116
optional< CoverRestoreState > restore_state_()
Definition cover.cpp:197
void publish_state(bool save=true)
Publish the current state of the cover.
Definition cover.cpp:163
void add_on_state_callback(std::function< void()> &&f)
Definition cover.cpp:162
CoverCall make_call()
Construct a new cover call used to control the cover.
Definition cover.cpp:146
float tilt
The current tilt value of the cover from 0.0 to 1.0.
Definition cover.h:124
float position
The position of the cover from 0.0 (fully closed) to 1.0 (fully open).
Definition cover.h:122
bool is_fully_closed() const
Helper method to check if the cover is fully closed. Equivalent to comparing .position against 0....
Definition cover.cpp:206
CallbackManager< void()> state_callback_
Definition cover.h:173
ESPPreferenceObject rtc_
Definition cover.h:175
virtual CoverTraits get_traits()=0
bool is_fully_open() const
Helper method to check if the cover is fully open. Equivalent to comparing .position against 1....
Definition cover.cpp:205
virtual void control(const CoverCall &call)=0
bool has_value() const
Definition optional.h:92
float position
Definition cover.h:0
float tilt
Definition cover.h:1
const float COVER_CLOSED
Definition cover.cpp:11
const float COVER_OPEN
Definition cover.cpp:10
const char * cover_command_to_str(float pos)
Definition cover.cpp:13
const char * cover_operation_to_str(CoverOperation op)
Definition cover.cpp:22
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
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
ESPPreferences * global_preferences
Struct used to store the restored state of a cover.
Definition cover.h:69
void apply(Cover *cover)
Apply these settings to the cover.
Definition cover.cpp:216
CoverCall to_call(Cover *cover)
Convert this struct to a cover call that can be performed.
Definition cover.cpp:208