add time based cover, has built in endstop (#665)

* add has built in endstop

* rewrite as proposed

* Update esphome/components/time_based/time_based_cover.h

Co-Authored-By: Otto Winter <otto@otto-winter.com>

* lint

* Re trigger stop_operation if stop called

* allow se triggering open/close command if safe

* using COVER_OPEN/CLOSE constants
This commit is contained in:
Guillermo Ruffino 2019-08-29 11:07:41 -03:00 committed by Otto Winter
parent d27291b997
commit 83a92f03fc
3 changed files with 23 additions and 4 deletions

View file

@ -8,6 +8,8 @@ from esphome.const import CONF_CLOSE_ACTION, CONF_CLOSE_DURATION, CONF_ID, CONF_
time_based_ns = cg.esphome_ns.namespace('time_based')
TimeBasedCover = time_based_ns.class_('TimeBasedCover', cover.Cover, cg.Component)
CONF_HAS_BUILT_IN_ENDSTOP = 'has_built_in_endstop'
CONFIG_SCHEMA = cover.COVER_SCHEMA.extend({
cv.GenerateID(): cv.declare_id(TimeBasedCover),
cv.Required(CONF_STOP_ACTION): automation.validate_automation(single=True),
@ -17,6 +19,8 @@ CONFIG_SCHEMA = cover.COVER_SCHEMA.extend({
cv.Required(CONF_CLOSE_ACTION): automation.validate_automation(single=True),
cv.Required(CONF_CLOSE_DURATION): cv.positive_time_period_milliseconds,
cv.Optional(CONF_HAS_BUILT_IN_ENDSTOP, default=False): cv.boolean,
}).extend(cv.COMPONENT_SCHEMA)
@ -32,3 +36,5 @@ def to_code(config):
cg.add(var.set_close_duration(config[CONF_CLOSE_DURATION]))
yield automation.build_automation(var.get_close_trigger(), [], config[CONF_CLOSE_ACTION])
cg.add(var.set_has_built_in_endstop(config[CONF_HAS_BUILT_IN_ENDSTOP]))

View file

@ -30,13 +30,18 @@ void TimeBasedCover::loop() {
// Recompute position every loop cycle
this->recompute_position_();
if (this->current_operation != COVER_OPERATION_IDLE && this->is_at_target_()) {
this->start_direction_(COVER_OPERATION_IDLE);
if (this->is_at_target_()) {
if (this->has_built_in_endstop_ && (this->target_position_ == COVER_OPEN || this->target_position_ == COVER_CLOSED)) {
// Don't trigger stop, let the cover stop by itself.
this->current_operation = COVER_OPERATION_IDLE;
} else {
this->start_direction_(COVER_OPERATION_IDLE);
}
this->publish_state();
}
// Send current position every second
if (this->current_operation != COVER_OPERATION_IDLE && now - this->last_publish_time_ > 1000) {
if (now - this->last_publish_time_ > 1000) {
this->publish_state(false);
this->last_publish_time_ = now;
}
@ -57,6 +62,12 @@ void TimeBasedCover::control(const CoverCall &call) {
auto pos = *call.get_position();
if (pos == this->position) {
// already at target
// for covers with built in end stop, we should send the command again
if (this->has_built_in_endstop_ && (pos == COVER_OPEN || pos == COVER_CLOSED)) {
auto op = pos == COVER_CLOSED ? COVER_OPERATION_CLOSING : COVER_OPERATION_OPENING;
this->target_position_ = pos;
this->start_direction_(op);
}
} else {
auto op = pos < this->position ? COVER_OPERATION_CLOSING : COVER_OPERATION_OPENING;
this->target_position_ = pos;
@ -82,7 +93,7 @@ bool TimeBasedCover::is_at_target_() const {
}
}
void TimeBasedCover::start_direction_(CoverOperation dir) {
if (dir == this->current_operation)
if (dir == this->current_operation && dir != COVER_OPERATION_IDLE)
return;
this->recompute_position_();

View file

@ -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; }
cover::CoverTraits get_traits() override;
void set_has_built_in_endstop(bool value) { this->has_built_in_endstop_ = value; }
protected:
void control(const cover::CoverCall &call) override;
@ -41,6 +42,7 @@ class TimeBasedCover : public cover::Cover, public Component {
uint32_t start_dir_time_{0};
uint32_t last_publish_time_{0};
float target_position_{0};
bool has_built_in_endstop_{false};
};
} // namespace time_based