[time_based] : Implemented support for time based tilt

This commit is contained in:
Adam Bogocz 2024-11-06 22:33:57 +00:00
parent 80b4c26481
commit 9630c60f4d
4 changed files with 41 additions and 4 deletions

View file

@ -1,15 +1,15 @@
import esphome.codegen as cg
import esphome.config_validation as cv
from esphome import automation from esphome import automation
import esphome.codegen as cg
from esphome.components import cover from esphome.components import cover
import esphome.config_validation as cv
from esphome.const import ( from esphome.const import (
CONF_ASSUMED_STATE,
CONF_CLOSE_ACTION, CONF_CLOSE_ACTION,
CONF_CLOSE_DURATION, CONF_CLOSE_DURATION,
CONF_ID, CONF_ID,
CONF_OPEN_ACTION, CONF_OPEN_ACTION,
CONF_OPEN_DURATION, CONF_OPEN_DURATION,
CONF_STOP_ACTION, CONF_STOP_ACTION,
CONF_ASSUMED_STATE,
) )
time_based_ns = cg.esphome_ns.namespace("time_based") time_based_ns = cg.esphome_ns.namespace("time_based")
@ -17,6 +17,7 @@ TimeBasedCover = time_based_ns.class_("TimeBasedCover", cover.Cover, cg.Componen
CONF_HAS_BUILT_IN_ENDSTOP = "has_built_in_endstop" CONF_HAS_BUILT_IN_ENDSTOP = "has_built_in_endstop"
CONF_MANUAL_CONTROL = "manual_control" CONF_MANUAL_CONTROL = "manual_control"
CONF_TILT_DURATION = "tilt_duration"
CONFIG_SCHEMA = cover.COVER_SCHEMA.extend( CONFIG_SCHEMA = cover.COVER_SCHEMA.extend(
{ {
@ -29,6 +30,9 @@ CONFIG_SCHEMA = cover.COVER_SCHEMA.extend(
cv.Optional(CONF_HAS_BUILT_IN_ENDSTOP, default=False): cv.boolean, cv.Optional(CONF_HAS_BUILT_IN_ENDSTOP, default=False): cv.boolean,
cv.Optional(CONF_MANUAL_CONTROL, default=False): cv.boolean, cv.Optional(CONF_MANUAL_CONTROL, default=False): cv.boolean,
cv.Optional(CONF_ASSUMED_STATE, default=True): cv.boolean, cv.Optional(CONF_ASSUMED_STATE, default=True): cv.boolean,
cv.Optional(
CONF_TILT_DURATION, default=0
): cv.positive_time_period_milliseconds,
} }
).extend(cv.COMPONENT_SCHEMA) ).extend(cv.COMPONENT_SCHEMA)
@ -55,3 +59,4 @@ async def to_code(config):
cg.add(var.set_has_built_in_endstop(config[CONF_HAS_BUILT_IN_ENDSTOP])) cg.add(var.set_has_built_in_endstop(config[CONF_HAS_BUILT_IN_ENDSTOP]))
cg.add(var.set_manual_control(config[CONF_MANUAL_CONTROL])) cg.add(var.set_manual_control(config[CONF_MANUAL_CONTROL]))
cg.add(var.set_assumed_state(config[CONF_ASSUMED_STATE])) cg.add(var.set_assumed_state(config[CONF_ASSUMED_STATE]))
cg.add(var.set_tilt_duration(config[CONF_TILT_DURATION]))

View file

@ -13,6 +13,9 @@ void TimeBasedCover::dump_config() {
LOG_COVER("", "Time Based Cover", this); LOG_COVER("", "Time Based Cover", this);
ESP_LOGCONFIG(TAG, " Open Duration: %.1fs", this->open_duration_ / 1e3f); ESP_LOGCONFIG(TAG, " Open Duration: %.1fs", this->open_duration_ / 1e3f);
ESP_LOGCONFIG(TAG, " Close Duration: %.1fs", this->close_duration_ / 1e3f); ESP_LOGCONFIG(TAG, " Close Duration: %.1fs", this->close_duration_ / 1e3f);
if (this->tilt_duration_ > 0)
ESP_LOGCONFIG(TAG, " Tilt Duration: %ums", this->tilt_duration_);
} }
void TimeBasedCover::setup() { void TimeBasedCover::setup() {
auto restore = this->restore_state_(); auto restore = this->restore_state_();
@ -54,6 +57,7 @@ CoverTraits TimeBasedCover::get_traits() {
traits.set_supports_stop(true); traits.set_supports_stop(true);
traits.set_supports_position(true); traits.set_supports_position(true);
traits.set_supports_toggle(true); traits.set_supports_toggle(true);
traits.set_supports_tilt(this->tilt_duration_ > 0);
traits.set_is_assumed_state(this->assumed_state_); traits.set_is_assumed_state(this->assumed_state_);
return traits; return traits;
} }
@ -103,6 +107,26 @@ void TimeBasedCover::control(const CoverCall &call) {
this->start_direction_(op); this->start_direction_(op);
} }
} }
if (call.get_tilt().has_value()) {
auto requested_tilt = *call.get_tilt();
if (requested_tilt != this->tilt) {
CoverOperation op;
uint32_t operation_duration_ms;
if (requested_tilt < this->tilt) {
op = COVER_OPERATION_CLOSING;
operation_duration_ms = this->close_duration_;
} else {
op = COVER_OPERATION_OPENING;
operation_duration_ms = this->open_duration_;
}
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;
this->start_direction_(op);
}
}
} }
void TimeBasedCover::stop_prev_trigger_() { void TimeBasedCover::stop_prev_trigger_() {
if (this->prev_command_trigger_ != nullptr) { if (this->prev_command_trigger_ != nullptr) {
@ -173,9 +197,14 @@ void TimeBasedCover::recompute_position_() {
} }
const uint32_t now = millis(); const uint32_t now = millis();
this->position += dir * (now - this->last_recompute_time_) / action_dur; 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->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; this->last_recompute_time_ = now;
} }

View file

@ -19,6 +19,7 @@ class TimeBasedCover : public cover::Cover, public Component {
Trigger<> *get_stop_trigger() const { return this->stop_trigger_; } Trigger<> *get_stop_trigger() const { return this->stop_trigger_; }
void set_open_duration(uint32_t open_duration) { this->open_duration_ = open_duration; } 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_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; }
cover::CoverTraits get_traits() override; cover::CoverTraits get_traits() override;
void set_has_built_in_endstop(bool value) { this->has_built_in_endstop_ = value; } void set_has_built_in_endstop(bool value) { this->has_built_in_endstop_ = value; }
void set_manual_control(bool value) { this->manual_control_ = value; } void set_manual_control(bool value) { this->manual_control_ = value; }
@ -39,6 +40,7 @@ class TimeBasedCover : public cover::Cover, public Component {
Trigger<> *close_trigger_{new Trigger<>()}; Trigger<> *close_trigger_{new Trigger<>()};
uint32_t close_duration_; uint32_t close_duration_;
Trigger<> *stop_trigger_{new Trigger<>()}; Trigger<> *stop_trigger_{new Trigger<>()};
uint32_t tilt_duration_;
Trigger<> *prev_command_trigger_{nullptr}; Trigger<> *prev_command_trigger_{nullptr};
uint32_t last_recompute_time_{0}; uint32_t last_recompute_time_{0};

View file

@ -10,3 +10,4 @@ cover:
close_action: close_action:
- logger.log: close_action - logger.log: close_action
close_duration: 4.5min close_duration: 4.5min
tilt_duration: 1s