8 static const char *
const TAG =
"feedback.cover";
13 auto restore = this->restore_state_();
15 if (restore.has_value()) {
23 #ifdef USE_BINARY_SENSOR 25 if (this->open_endstop_ !=
nullptr && this->open_endstop_->state) {
27 }
else if (this->close_endstop_ !=
nullptr && this->close_endstop_->state) {
32 if (this->open_feedback_ !=
nullptr && this->open_feedback_->state) {
34 }
else if (this->close_feedback_ !=
nullptr && this->close_feedback_->state) {
39 this->last_recompute_time_ = this->start_dir_time_ =
millis();
44 traits.set_supports_position(
true);
45 traits.set_supports_toggle(
true);
46 traits.set_is_assumed_state(this->assumed_state_);
51 LOG_COVER(
"",
"Endstop Cover",
this);
52 ESP_LOGCONFIG(TAG,
" Open Duration: %.1fs", this->open_duration_ / 1e3f);
53 #ifdef USE_BINARY_SENSOR 54 LOG_BINARY_SENSOR(
" ",
"Open Endstop", this->open_endstop_);
55 LOG_BINARY_SENSOR(
" ",
"Open Feedback", this->open_feedback_);
56 LOG_BINARY_SENSOR(
" ",
"Open Obstacle", this->open_obstacle_);
58 ESP_LOGCONFIG(TAG,
" Close Duration: %.1fs", this->close_duration_ / 1e3f);
59 #ifdef USE_BINARY_SENSOR 60 LOG_BINARY_SENSOR(
" ",
"Close Endstop", this->close_endstop_);
61 LOG_BINARY_SENSOR(
" ",
"Close Feedback", this->close_feedback_);
62 LOG_BINARY_SENSOR(
" ",
"Close Obstacle", this->close_obstacle_);
64 if (this->has_built_in_endstop_) {
65 ESP_LOGCONFIG(TAG,
" Has builtin endstop: YES");
67 if (this->infer_endstop_) {
68 ESP_LOGCONFIG(TAG,
" Infer endstop from movement: YES");
70 if (this->max_duration_ < UINT32_MAX) {
71 ESP_LOGCONFIG(TAG,
" Max Duration: %.1fs", this->max_duration_ / 1e3f);
73 if (this->direction_change_waittime_.has_value()) {
74 ESP_LOGCONFIG(TAG,
" Direction change wait time: %.1fs", *this->direction_change_waittime_ / 1e3f);
76 if (this->acceleration_wait_time_) {
77 ESP_LOGCONFIG(TAG,
" Acceleration wait time: %.1fs", this->acceleration_wait_time_ / 1e3f);
79 #ifdef USE_BINARY_SENSOR 80 if (this->obstacle_rollback_ && (this->open_obstacle_ !=
nullptr || this->close_obstacle_ !=
nullptr)) {
81 ESP_LOGCONFIG(TAG,
" Obstacle rollback: %.1f%%", this->obstacle_rollback_ * 100);
86 #ifdef USE_BINARY_SENSOR 89 this->open_feedback_ = open_feedback;
93 ESP_LOGD(TAG,
"'%s' - Open feedback '%s'.", this->name_.c_str(), state ?
"STARTED" :
"ENDED");
94 this->recompute_position_();
96 this->endstop_reached_(
true);
103 this->close_feedback_ = close_feedback;
106 ESP_LOGD(TAG,
"'%s' - Close feedback '%s'.", this->name_.c_str(), state ?
"STARTED" :
"ENDED");
107 this->recompute_position_();
109 this->endstop_reached_(
false);
117 this->open_endstop_ = open_endstop;
120 this->endstop_reached_(
true);
126 this->close_endstop_ = close_endstop;
129 this->endstop_reached_(
false);
136 const uint32_t now =
millis();
143 float dur = (now - this->start_dir_time_) / 1e3f;
144 ESP_LOGD(TAG,
"'%s' - %s endstop reached. Took %.1fs.", this->name_.c_str(), open_endstop ?
"Open" :
"Close", dur);
147 if (!this->has_built_in_endstop_) {
155 this->publish_state();
156 this->last_publish_time_ = now;
161 this->current_trigger_operation_ = operation;
171 #ifdef USE_BINARY_SENSOR 172 if (!is_triggered || (this->open_feedback_ ==
nullptr || this->close_feedback_ ==
nullptr))
176 this->current_operation = operation;
177 this->start_dir_time_ = this->last_recompute_time_ = now;
178 this->publish_state();
179 this->last_publish_time_ = now;
183 #ifdef USE_BINARY_SENSOR 185 this->close_obstacle_ = close_obstacle;
190 ESP_LOGD(TAG,
"'%s' - Close obstacle detected.", this->name_.c_str());
193 if (this->obstacle_rollback_) {
202 this->open_obstacle_ = open_obstacle;
207 ESP_LOGD(TAG,
"'%s' - Open obstacle detected.", this->name_.c_str());
210 if (this->obstacle_rollback_) {
222 const uint32_t now =
millis();
225 this->recompute_position_();
230 if (this->is_at_target_()) {
231 if (this->has_built_in_endstop_ &&
238 }
else if (now - this->start_dir_time_ > this->max_duration_) {
239 ESP_LOGD(TAG,
"'%s' - Max duration reached. Stopping cover.", this->name_.c_str());
247 if (now - this->last_publish_time_ > this->update_interval_) {
248 this->publish_state(
false);
249 this->last_publish_time_ = now;
278 if (this->has_built_in_endstop_ && ((pos ==
COVER_OPEN 279 #ifdef USE_BINARY_SENSOR
280 && this->open_endstop_ ==
nullptr 282 && !this->infer_endstop_) ||
284 #ifdef USE_BINARY_SENSOR
285 && this->close_endstop_ ==
nullptr 287 && !this->infer_endstop_))) {
288 this->target_position_ = pos;
296 this->target_position_ = pos;
303 if (this->direction_change_waittime_.has_value()) {
304 this->cancel_timeout(
"direction_change");
306 if (this->prev_command_trigger_ !=
nullptr) {
307 this->prev_command_trigger_->stop_action();
308 this->prev_command_trigger_ =
nullptr;
316 switch (this->current_trigger_operation_) {
318 return this->
position >= this->target_position_;
320 return this->
position <= this->target_position_;
330 #ifdef USE_BINARY_SENSOR 336 trig = this->stop_trigger_;
339 this->last_operation_ = dir;
340 trig = this->open_trigger_;
341 #ifdef USE_BINARY_SENSOR 342 obstacle = this->open_obstacle_;
346 this->last_operation_ = dir;
347 trig = this->close_trigger_;
348 #ifdef USE_BINARY_SENSOR 349 obstacle = this->close_obstacle_;
356 this->stop_prev_trigger_();
358 #ifdef USE_BINARY_SENSOR 361 if (obstacle !=
nullptr && obstacle->state) {
362 ESP_LOGD(TAG,
"'%s' - %s obstacle detected. Action not started.", this->name_.c_str(),
372 ESP_LOGD(TAG,
"'%s' - Reversing direction.", this->name_.c_str());
375 this->set_timeout(
"direction_change", *this->direction_change_waittime_,
376 [
this, dir]() { this->start_direction_(dir); });
379 this->set_current_operation_(dir,
true);
380 this->prev_command_trigger_ = trig;
381 ESP_LOGD(TAG,
"'%s' - Firing '%s' trigger.", this->name_.c_str(),
393 const uint32_t now =
millis();
403 switch (this->current_operation) {
406 action_dur = this->open_duration_;
409 #ifdef USE_BINARY_SENSOR 410 this->open_endstop_ !=
nullptr ||
412 this->infer_endstop_) &&
419 action_dur = this->close_duration_;
421 #ifdef USE_BINARY_SENSOR 422 this->close_endstop_ !=
nullptr ||
424 this->infer_endstop_) &&
435 if (now > (this->start_dir_time_ + this->acceleration_wait_time_)) {
437 dir * (now - std::max(this->start_dir_time_ + this->acceleration_wait_time_, this->last_recompute_time_)) /
438 (action_dur - this->acceleration_wait_time_);
441 this->last_recompute_time_ = now;
void set_close_endstop(binary_sensor::BinarySensor *close_endstop)
void set_current_operation_(cover::CoverOperation operation, bool is_triggered)
void endstop_reached_(bool open_endstop)
CoverOperation
Enum encoding the current operation of a cover.
The cover is currently closing.
constexpr const T & clamp(const T &v, const T &lo, const T &hi, Compare comp)
uint32_t IRAM_ATTR HOT millis()
void trigger(Ts... x)
Inform the parent automation that the event has triggered.
void dump_config() override
void set_open_sensor(binary_sensor::BinarySensor *open_feedback)
bool is_at_target_() const
void control(const cover::CoverCall &call) override
void start_direction_(cover::CoverOperation dir)
const optional< bool > & get_toggle() const
void set_close_obstacle_sensor(binary_sensor::BinarySensor *close_obstacle)
void recompute_position_()
void set_close_sensor(binary_sensor::BinarySensor *close_feedback)
void set_open_endstop(binary_sensor::BinarySensor *open_endstop)
cover::CoverTraits get_traits() override
void add_on_state_callback(std::function< void(bool)> &&callback)
Add a callback to be notified of state changes.
Base class for all binary_sensor-type classes.
void set_open_obstacle_sensor(binary_sensor::BinarySensor *open_obstacle)
void stop_prev_trigger_()
The cover is currently opening.
const optional< float > & get_position() const