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_stop(
true);
45 traits.set_supports_position(
true);
46 traits.set_supports_toggle(
true);
47 traits.set_is_assumed_state(this->assumed_state_);
52 LOG_COVER(
"",
"Endstop Cover",
this);
53 ESP_LOGCONFIG(TAG,
" Open Duration: %.1fs", this->open_duration_ / 1e3f);
54 #ifdef USE_BINARY_SENSOR 55 LOG_BINARY_SENSOR(
" ",
"Open Endstop", this->open_endstop_);
56 LOG_BINARY_SENSOR(
" ",
"Open Feedback", this->open_feedback_);
57 LOG_BINARY_SENSOR(
" ",
"Open Obstacle", this->open_obstacle_);
59 ESP_LOGCONFIG(TAG,
" Close Duration: %.1fs", this->close_duration_ / 1e3f);
60 #ifdef USE_BINARY_SENSOR 61 LOG_BINARY_SENSOR(
" ",
"Close Endstop", this->close_endstop_);
62 LOG_BINARY_SENSOR(
" ",
"Close Feedback", this->close_feedback_);
63 LOG_BINARY_SENSOR(
" ",
"Close Obstacle", this->close_obstacle_);
65 if (this->has_built_in_endstop_) {
66 ESP_LOGCONFIG(TAG,
" Has builtin endstop: YES");
68 if (this->infer_endstop_) {
69 ESP_LOGCONFIG(TAG,
" Infer endstop from movement: YES");
71 if (this->max_duration_ < UINT32_MAX) {
72 ESP_LOGCONFIG(TAG,
" Max Duration: %.1fs", this->max_duration_ / 1e3f);
74 if (this->direction_change_waittime_.has_value()) {
75 ESP_LOGCONFIG(TAG,
" Direction change wait time: %.1fs", *this->direction_change_waittime_ / 1e3f);
77 if (this->acceleration_wait_time_) {
78 ESP_LOGCONFIG(TAG,
" Acceleration wait time: %.1fs", this->acceleration_wait_time_ / 1e3f);
80 #ifdef USE_BINARY_SENSOR 81 if (this->obstacle_rollback_ && (this->open_obstacle_ !=
nullptr || this->close_obstacle_ !=
nullptr)) {
82 ESP_LOGCONFIG(TAG,
" Obstacle rollback: %.1f%%", this->obstacle_rollback_ * 100);
87 #ifdef USE_BINARY_SENSOR 90 this->open_feedback_ = open_feedback;
94 ESP_LOGD(TAG,
"'%s' - Open feedback '%s'.", this->name_.c_str(), state ?
"STARTED" :
"ENDED");
95 this->recompute_position_();
97 this->endstop_reached_(
true);
104 this->close_feedback_ = close_feedback;
107 ESP_LOGD(TAG,
"'%s' - Close feedback '%s'.", this->name_.c_str(), state ?
"STARTED" :
"ENDED");
108 this->recompute_position_();
110 this->endstop_reached_(
false);
118 this->open_endstop_ = open_endstop;
121 this->endstop_reached_(
true);
127 this->close_endstop_ = close_endstop;
130 this->endstop_reached_(
false);
137 const uint32_t now =
millis();
144 float dur = (now - this->start_dir_time_) / 1e3f;
145 ESP_LOGD(TAG,
"'%s' - %s endstop reached. Took %.1fs.", this->name_.c_str(), open_endstop ?
"Open" :
"Close", dur);
148 if (!this->has_built_in_endstop_) {
156 this->publish_state();
157 this->last_publish_time_ = now;
162 this->current_trigger_operation_ = operation;
172 #ifdef USE_BINARY_SENSOR 173 if (!is_triggered || (this->open_feedback_ ==
nullptr || this->close_feedback_ ==
nullptr))
177 this->current_operation = operation;
178 this->start_dir_time_ = this->last_recompute_time_ = now;
179 this->publish_state();
180 this->last_publish_time_ = now;
184 #ifdef USE_BINARY_SENSOR 186 this->close_obstacle_ = close_obstacle;
191 ESP_LOGD(TAG,
"'%s' - Close obstacle detected.", this->name_.c_str());
194 if (this->obstacle_rollback_) {
203 this->open_obstacle_ = open_obstacle;
208 ESP_LOGD(TAG,
"'%s' - Open obstacle detected.", this->name_.c_str());
211 if (this->obstacle_rollback_) {
223 const uint32_t now =
millis();
226 this->recompute_position_();
231 if (this->is_at_target_()) {
232 if (this->has_built_in_endstop_ &&
239 }
else if (now - this->start_dir_time_ > this->max_duration_) {
240 ESP_LOGD(TAG,
"'%s' - Max duration reached. Stopping cover.", this->name_.c_str());
248 if (now - this->last_publish_time_ > this->update_interval_) {
249 this->publish_state(
false);
250 this->last_publish_time_ = now;
279 if (this->has_built_in_endstop_ && ((pos ==
COVER_OPEN 280 #ifdef USE_BINARY_SENSOR
281 && this->open_endstop_ ==
nullptr 283 && !this->infer_endstop_) ||
285 #ifdef USE_BINARY_SENSOR
286 && this->close_endstop_ ==
nullptr 288 && !this->infer_endstop_))) {
289 this->target_position_ = pos;
297 this->target_position_ = pos;
304 if (this->direction_change_waittime_.has_value()) {
305 this->cancel_timeout(
"direction_change");
307 if (this->prev_command_trigger_ !=
nullptr) {
308 this->prev_command_trigger_->stop_action();
309 this->prev_command_trigger_ =
nullptr;
317 switch (this->current_trigger_operation_) {
319 return this->
position >= this->target_position_;
321 return this->
position <= this->target_position_;
331 #ifdef USE_BINARY_SENSOR 337 trig = this->stop_trigger_;
340 this->last_operation_ = dir;
341 trig = this->open_trigger_;
342 #ifdef USE_BINARY_SENSOR 343 obstacle = this->open_obstacle_;
347 this->last_operation_ = dir;
348 trig = this->close_trigger_;
349 #ifdef USE_BINARY_SENSOR 350 obstacle = this->close_obstacle_;
357 this->stop_prev_trigger_();
359 #ifdef USE_BINARY_SENSOR 362 if (obstacle !=
nullptr && obstacle->state) {
363 ESP_LOGD(TAG,
"'%s' - %s obstacle detected. Action not started.", this->name_.c_str(),
373 ESP_LOGD(TAG,
"'%s' - Reversing direction.", this->name_.c_str());
376 this->set_timeout(
"direction_change", *this->direction_change_waittime_,
377 [
this, dir]() { this->start_direction_(dir); });
380 this->set_current_operation_(dir,
true);
381 this->prev_command_trigger_ = trig;
382 ESP_LOGD(TAG,
"'%s' - Firing '%s' trigger.", this->name_.c_str(),
394 const uint32_t now =
millis();
404 switch (this->current_operation) {
407 action_dur = this->open_duration_;
410 #ifdef USE_BINARY_SENSOR 411 this->open_endstop_ !=
nullptr ||
413 this->infer_endstop_) &&
420 action_dur = this->close_duration_;
422 #ifdef USE_BINARY_SENSOR 423 this->close_endstop_ !=
nullptr ||
425 this->infer_endstop_) &&
436 if (now > (this->start_dir_time_ + this->acceleration_wait_time_)) {
438 dir * (now - std::max(this->start_dir_time_ + this->acceleration_wait_time_, this->last_recompute_time_)) /
439 (action_dur - this->acceleration_wait_time_);
442 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.
Implementation of SPI Controller mode.
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