diff --git a/esphome/components/time_based/cover.py b/esphome/components/time_based/cover.py index 0a9eb683e9..439f3407ba 100644 --- a/esphome/components/time_based/cover.py +++ b/esphome/components/time_based/cover.py @@ -18,6 +18,7 @@ TimeBasedCover = time_based_ns.class_("TimeBasedCover", cover.Cover, cg.Componen CONF_HAS_BUILT_IN_ENDSTOP = "has_built_in_endstop" CONF_MANUAL_CONTROL = "manual_control" CONF_TILT_DURATION = "tilt_duration" +CONF_ACTIVATION_DELAY = "activation_delay" CONFIG_SCHEMA = cover.COVER_SCHEMA.extend( { @@ -31,7 +32,10 @@ CONFIG_SCHEMA = cover.COVER_SCHEMA.extend( cv.Optional(CONF_MANUAL_CONTROL, default=False): cv.boolean, cv.Optional(CONF_ASSUMED_STATE, default=True): cv.boolean, cv.Optional( - CONF_TILT_DURATION, default=0 + CONF_TILT_DURATION, default="0s" + ): cv.positive_time_period_milliseconds, + cv.Optional( + CONF_ACTIVATION_DELAY, default="0s" ): cv.positive_time_period_milliseconds, } ).extend(cv.COMPONENT_SCHEMA) @@ -60,3 +64,4 @@ async def to_code(config): cg.add(var.set_manual_control(config[CONF_MANUAL_CONTROL])) cg.add(var.set_assumed_state(config[CONF_ASSUMED_STATE])) cg.add(var.set_tilt_duration(config[CONF_TILT_DURATION])) + cg.add(var.set_activation_delay(config[CONF_ACTIVATION_DELAY])) diff --git a/esphome/components/time_based/time_based_cover.cpp b/esphome/components/time_based/time_based_cover.cpp index 661916f9e4..84a603d269 100644 --- a/esphome/components/time_based/time_based_cover.cpp +++ b/esphome/components/time_based/time_based_cover.cpp @@ -16,6 +16,8 @@ void TimeBasedCover::dump_config() { if (this->tilt_duration_ > 0) ESP_LOGCONFIG(TAG, " Tilt Duration: %ums", this->tilt_duration_); + + ESP_LOGCONFIG(TAG, " Activation delay: %ums", this->activation_delay_); } void TimeBasedCover::setup() { auto restore = this->restore_state_(); @@ -122,8 +124,9 @@ void TimeBasedCover::control(const CoverCall &call) { } const auto tilt_change_duration_ms = (requested_tilt - this->tilt) * this->tilt_duration_; - const auto new_pos = tilt_change_duration_ms / operation_duration_ms; - this->target_position_ += new_pos; + const auto position_shift = tilt_change_duration_ms / operation_duration_ms; + + this->target_position_ = this->position + position_shift; this->start_direction_(op); } } @@ -176,6 +179,7 @@ void TimeBasedCover::start_direction_(CoverOperation dir) { this->stop_prev_trigger_(); trig->trigger(); this->prev_command_trigger_ = trig; + this->remaining_activation_delay_ = this->activation_delay_; } void TimeBasedCover::recompute_position_() { if (this->current_operation == COVER_OPERATION_IDLE) @@ -199,11 +203,17 @@ void TimeBasedCover::recompute_position_() { const uint32_t now = millis(); const uint32_t step_duration = now - this->last_recompute_time_; - this->position += dir * (step_duration) / action_dur; - this->position = clamp(this->position, 0.0f, 1.0f); + this->remaining_activation_delay_ -= step_duration; - this->tilt += dir * (step_duration) / this->tilt_duration_; - this->tilt = clamp(this->tilt, 0.0f, 1.0f); + if (this->remaining_activation_delay_ <= 0) { + this->remaining_activation_delay_ = 0; + + this->position += dir * (step_duration) / action_dur; + this->position = clamp(this->position, 0.0f, 1.0f); + + this->tilt += dir * (step_duration) / this->tilt_duration_; + this->tilt = clamp(this->tilt, 0.0f, 1.0f); + } this->last_recompute_time_ = now; } diff --git a/esphome/components/time_based/time_based_cover.h b/esphome/components/time_based/time_based_cover.h index f2f7518909..e612bb9e6d 100644 --- a/esphome/components/time_based/time_based_cover.h +++ b/esphome/components/time_based/time_based_cover.h @@ -20,6 +20,7 @@ class TimeBasedCover : public cover::Cover, public Component { void set_open_duration(uint32_t open_duration) { this->open_duration_ = open_duration; } void set_close_duration(uint32_t close_duration) { this->close_duration_ = close_duration; } void set_tilt_duration(uint32_t tilt_duration_ms) { this->tilt_duration_ = tilt_duration_ms; } + void set_activation_delay(uint32_t activation_delay_ms) { this->activation_delay_ = activation_delay_ms; } cover::CoverTraits get_traits() override; void set_has_built_in_endstop(bool value) { this->has_built_in_endstop_ = value; } void set_manual_control(bool value) { this->manual_control_ = value; } @@ -41,11 +42,13 @@ class TimeBasedCover : public cover::Cover, public Component { uint32_t close_duration_; Trigger<> *stop_trigger_{new Trigger<>()}; uint32_t tilt_duration_; + uint32_t activation_delay_; Trigger<> *prev_command_trigger_{nullptr}; uint32_t last_recompute_time_{0}; uint32_t start_dir_time_{0}; uint32_t last_publish_time_{0}; + int32_t remaining_activation_delay_{0}; float target_position_{0}; bool has_built_in_endstop_{false}; bool manual_control_{false}; diff --git a/tests/components/time_based/common.yaml b/tests/components/time_based/common.yaml index ff3f36b3bb..a2042f9f78 100644 --- a/tests/components/time_based/common.yaml +++ b/tests/components/time_based/common.yaml @@ -11,3 +11,4 @@ cover: - logger.log: close_action close_duration: 4.5min tilt_duration: 1s + activation_delay: 300ms