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