mirror of
https://github.com/esphome/esphome.git
synced 2024-11-27 09:18:00 +01:00
Refactoring – simplified.
Added actuator activation time. Separated recalibration times for opening and closing. Rounded position after stopping; saved rounded position and tilt values. Added debug logging. Stopped as needed in calibration state after receiving control requests.
This commit is contained in:
parent
9fcdbbb02d
commit
48dabe0a80
3 changed files with 154 additions and 88 deletions
|
@ -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,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
CODEOWNERS = ["@klaudiusz223"]
|
CODEOWNERS = ["@klaudiusz223"]
|
||||||
|
@ -22,7 +22,10 @@ TimeBasedTiltCover = time_based_tilt_ns.class_(
|
||||||
CONF_TILT_OPEN_DURATION = "tilt_open_duration"
|
CONF_TILT_OPEN_DURATION = "tilt_open_duration"
|
||||||
CONF_TILT_CLOSE_DURATION = "tilt_close_duration"
|
CONF_TILT_CLOSE_DURATION = "tilt_close_duration"
|
||||||
CONF_INTERLOCK_WAIT_TIME = "interlock_wait_time"
|
CONF_INTERLOCK_WAIT_TIME = "interlock_wait_time"
|
||||||
CONF_RECALIBRATION_TIME = "recalibration_time"
|
CONF_RECALIBRATION_OPEN_TIME = "recalibration_open_time"
|
||||||
|
CONF_RECALIBRATION_CLOSE_TIME = "recalibration_close_time"
|
||||||
|
CONF_ACTUATOR_ACTIVATION_OPEN_TIME = "actuator_activation_open_time"
|
||||||
|
CONF_ACTUATOR_ACTIVATION_CLOSE_TIME = "actuator_activation_close_time"
|
||||||
CONF_INERTIA_OPEN_TIME = "inertia_open_time"
|
CONF_INERTIA_OPEN_TIME = "inertia_open_time"
|
||||||
CONF_INERTIA_CLOSE_TIME = "inertia_close_time"
|
CONF_INERTIA_CLOSE_TIME = "inertia_close_time"
|
||||||
|
|
||||||
|
@ -45,7 +48,10 @@ CONFIG_SCHEMA = cover.COVER_SCHEMA.extend(
|
||||||
CONF_INTERLOCK_WAIT_TIME, default="0ms"
|
CONF_INTERLOCK_WAIT_TIME, default="0ms"
|
||||||
): cv.positive_time_period_milliseconds,
|
): cv.positive_time_period_milliseconds,
|
||||||
cv.Optional(
|
cv.Optional(
|
||||||
CONF_RECALIBRATION_TIME, default="0ms"
|
CONF_RECALIBRATION_OPEN_TIME, default="0ms"
|
||||||
|
): cv.positive_time_period_milliseconds,
|
||||||
|
cv.Optional(
|
||||||
|
CONF_RECALIBRATION_CLOSE_TIME, default="0ms"
|
||||||
): cv.positive_time_period_milliseconds,
|
): cv.positive_time_period_milliseconds,
|
||||||
cv.Optional(
|
cv.Optional(
|
||||||
CONF_INERTIA_OPEN_TIME, default="0ms"
|
CONF_INERTIA_OPEN_TIME, default="0ms"
|
||||||
|
@ -53,6 +59,12 @@ CONFIG_SCHEMA = cover.COVER_SCHEMA.extend(
|
||||||
cv.Optional(
|
cv.Optional(
|
||||||
CONF_INERTIA_CLOSE_TIME, default="0ms"
|
CONF_INERTIA_CLOSE_TIME, default="0ms"
|
||||||
): cv.positive_time_period_milliseconds,
|
): cv.positive_time_period_milliseconds,
|
||||||
|
cv.Optional(
|
||||||
|
CONF_ACTUATOR_ACTIVATION_OPEN_TIME, default="0ms"
|
||||||
|
): cv.positive_time_period_milliseconds,
|
||||||
|
cv.Optional(
|
||||||
|
CONF_ACTUATOR_ACTIVATION_CLOSE_TIME, default="0ms"
|
||||||
|
): cv.positive_time_period_milliseconds,
|
||||||
}
|
}
|
||||||
).extend(cv.COMPONENT_SCHEMA)
|
).extend(cv.COMPONENT_SCHEMA)
|
||||||
|
|
||||||
|
@ -79,7 +91,18 @@ async def to_code(config):
|
||||||
cg.add(var.set_tilt_open_duration(config[CONF_TILT_OPEN_DURATION]))
|
cg.add(var.set_tilt_open_duration(config[CONF_TILT_OPEN_DURATION]))
|
||||||
cg.add(var.set_tilt_close_duration(config[CONF_TILT_CLOSE_DURATION]))
|
cg.add(var.set_tilt_close_duration(config[CONF_TILT_CLOSE_DURATION]))
|
||||||
cg.add(var.set_interlock_wait_time(config[CONF_INTERLOCK_WAIT_TIME]))
|
cg.add(var.set_interlock_wait_time(config[CONF_INTERLOCK_WAIT_TIME]))
|
||||||
cg.add(var.set_recalibration_time(config[CONF_RECALIBRATION_TIME]))
|
cg.add(var.set_recalibration_open_time(config[CONF_RECALIBRATION_OPEN_TIME]))
|
||||||
|
cg.add(var.set_recalibration_close_time(config[CONF_RECALIBRATION_CLOSE_TIME]))
|
||||||
cg.add(var.set_inertia_close_time(config[CONF_INERTIA_CLOSE_TIME]))
|
cg.add(var.set_inertia_close_time(config[CONF_INERTIA_CLOSE_TIME]))
|
||||||
cg.add(var.set_inertia_open_time(config[CONF_INERTIA_OPEN_TIME]))
|
cg.add(var.set_inertia_open_time(config[CONF_INERTIA_OPEN_TIME]))
|
||||||
cg.add(var.set_assumed_state(config[CONF_ASSUMED_STATE]))
|
cg.add(var.set_assumed_state(config[CONF_ASSUMED_STATE]))
|
||||||
|
cg.add(
|
||||||
|
var.set_actuator_activation_open_time(
|
||||||
|
config[CONF_ACTUATOR_ACTIVATION_OPEN_TIME]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
cg.add(
|
||||||
|
var.set_actuator_activation_close_time(
|
||||||
|
config[CONF_ACTUATOR_ACTIVATION_CLOSE_TIME]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
|
@ -20,7 +20,12 @@ void TimeBasedTiltCover::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, " Interlock wait time: %.3fs", this->interlock_wait_time_ / 1e3f);
|
ESP_LOGCONFIG(TAG, " Interlock wait time: %.3fs", this->interlock_wait_time_ / 1e3f);
|
||||||
ESP_LOGCONFIG(TAG, " Inertia close time: %.3fs", this->inertia_close_time_ / 1e3f);
|
ESP_LOGCONFIG(TAG, " Inertia close time: %.3fs", this->inertia_close_time_ / 1e3f);
|
||||||
ESP_LOGCONFIG(TAG, " Inertia open time: %.3fs", this->inertia_open_time_ / 1e3f);
|
ESP_LOGCONFIG(TAG, " Inertia open time: %.3fs", this->inertia_open_time_ / 1e3f);
|
||||||
ESP_LOGCONFIG(TAG, " Recalibration time: %.3fs", this->recalibration_time_ / 1e3f);
|
ESP_LOGCONFIG(TAG, " Recalibration close time: %.3fs", this->recalibration_close_time_ / 1e3f);
|
||||||
|
ESP_LOGCONFIG(TAG, " Recalibration open time: %.3fs", this->recalibration_open_time_ / 1e3f);
|
||||||
|
ESP_LOGCONFIG(TAG, " Actuator activation close time: %.3fs", this->actuator_activation_close_time_ / 1e3f);
|
||||||
|
ESP_LOGCONFIG(TAG, " Actuator activation open time: %.3fs", this->actuator_activation_open_time_ / 1e3f);
|
||||||
|
ESP_LOGCONFIG(TAG, " Current position: %.4f", this->position);
|
||||||
|
ESP_LOGCONFIG(TAG, " Current tilt: %.4f", this->tilt);
|
||||||
}
|
}
|
||||||
void TimeBasedTiltCover::setup() {
|
void TimeBasedTiltCover::setup() {
|
||||||
if (this->tilt_close_duration_ == 0 || this->tilt_open_duration_ == 0) {
|
if (this->tilt_close_duration_ == 0 || this->tilt_open_duration_ == 0) {
|
||||||
|
@ -59,6 +64,11 @@ bool TimeBasedTiltCover::is_at_target_tilt_() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TimeBasedTiltCover::is_at_extreme_position_() const {
|
||||||
|
return (this->position == COVER_CLOSED && (tilt_close_duration_ == 0 || this->tilt == COVER_CLOSED)) ||
|
||||||
|
(this->position == COVER_OPEN && (tilt_open_duration_ == 0 || this->tilt == COVER_OPEN));
|
||||||
|
}
|
||||||
|
|
||||||
void TimeBasedTiltCover::loop() {
|
void TimeBasedTiltCover::loop() {
|
||||||
if (this->fsm_state_ == STATE_IDLE && this->target_position_ == TARGET_NONE && this->target_tilt_ == TARGET_NONE)
|
if (this->fsm_state_ == STATE_IDLE && this->target_position_ == TARGET_NONE && this->target_tilt_ == TARGET_NONE)
|
||||||
return;
|
return;
|
||||||
|
@ -67,13 +77,14 @@ void TimeBasedTiltCover::loop() {
|
||||||
|
|
||||||
// recalibrating in extreme postions
|
// recalibrating in extreme postions
|
||||||
if (this->fsm_state_ == STATE_CALIBRATING) {
|
if (this->fsm_state_ == STATE_CALIBRATING) {
|
||||||
if (now - this->last_recompute_time_ >= this->recalibration_time_) {
|
if (now - this->last_recompute_time_ >= this->current_recalibration_time_) {
|
||||||
this->fsm_state_ = STATE_STOPPING;
|
this->fsm_state_ = STATE_STOPPING;
|
||||||
|
ESP_LOGD(TAG, "Transition to the stopping state");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STOPPING - determining the direction of the last movement and the stopping time. Needed to support interlocking
|
// STOPPING – determining the direction of the last movement and the stopping time. Necessary to support interlocking.
|
||||||
if (this->fsm_state_ == STATE_STOPPING) {
|
if (this->fsm_state_ == STATE_STOPPING) {
|
||||||
this->stop_trigger_->trigger();
|
this->stop_trigger_->trigger();
|
||||||
if (this->current_operation != COVER_OPERATION_IDLE) {
|
if (this->current_operation != COVER_OPERATION_IDLE) {
|
||||||
|
@ -84,30 +95,55 @@ void TimeBasedTiltCover::loop() {
|
||||||
this->interlocked_direction_ = COVER_OPERATION_IDLE;
|
this->interlocked_direction_ = COVER_OPERATION_IDLE;
|
||||||
}
|
}
|
||||||
this->fsm_state_ = STATE_IDLE;
|
this->fsm_state_ = STATE_IDLE;
|
||||||
|
ESP_LOGD(TAG, "Transition to the idle state");
|
||||||
this->last_operation_ = this->current_operation;
|
this->last_operation_ = this->current_operation;
|
||||||
this->current_operation = COVER_OPERATION_IDLE;
|
this->current_operation = COVER_OPERATION_IDLE;
|
||||||
|
this->position = this->round_position(this->position);
|
||||||
|
this->tilt = this->round_position(this->tilt);
|
||||||
this->publish_state();
|
this->publish_state();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the cover is not moving, check whether the new targets are set and if they are, compute move direction
|
// If the cover is not moving, check whether new targets are set. If they are, compute the movement direction.
|
||||||
if (this->fsm_state_ == STATE_IDLE && (this->target_position_ != TARGET_NONE || this->target_tilt_ != TARGET_NONE)) {
|
if (this->fsm_state_ == STATE_IDLE && (this->target_position_ != TARGET_NONE || this->target_tilt_ != TARGET_NONE)) {
|
||||||
if (this->target_position_ != TARGET_NONE) {
|
if (this->target_position_ != TARGET_NONE) { // First, calculate based on the target position.
|
||||||
this->current_operation = this->compute_direction(this->target_position_, this->position);
|
this->current_operation = this->compute_direction(this->target_position_, this->position);
|
||||||
} else {
|
if (this->current_operation == COVER_OPERATION_IDLE) { // Already at the target position.
|
||||||
this->current_operation = this->compute_direction(this->target_tilt_, this->tilt);
|
this->target_position_ = TARGET_NONE;
|
||||||
|
if (this->target_tilt_ != TARGET_NONE) {
|
||||||
|
this->current_operation = this->compute_direction(
|
||||||
|
this->target_tilt_, this->tilt); // Calculate the direction based on the target tilt.
|
||||||
}
|
}
|
||||||
// interlocking support
|
}
|
||||||
|
} else {
|
||||||
|
this->current_operation =
|
||||||
|
this->compute_direction(this->target_tilt_, this->tilt); // Calculate the direction based on the target tilt.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->current_operation == COVER_OPERATION_IDLE) { // Already at the target tilt and target position.
|
||||||
|
this->target_tilt_ = TARGET_NONE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Interlocking support.
|
||||||
if (this->current_operation == this->interlocked_direction_ &&
|
if (this->current_operation == this->interlocked_direction_ &&
|
||||||
now - this->interlocked_time_ < this->interlock_wait_time_)
|
now - this->interlocked_time_ < this->interlock_wait_time_)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Trigger<> *trig = this->current_operation == COVER_OPERATION_CLOSING ? this->close_trigger_ : this->open_trigger_;
|
Trigger<> *trig = this->current_operation == COVER_OPERATION_CLOSING ? this->close_trigger_ : this->open_trigger_;
|
||||||
|
|
||||||
|
this->current_recalibration_time_ = this->current_operation == COVER_OPERATION_CLOSING
|
||||||
|
? this->recalibration_close_time_
|
||||||
|
: this->recalibration_open_time_;
|
||||||
|
this->current_actuator_activation_time_ = this->current_operation == COVER_OPERATION_CLOSING
|
||||||
|
? this->actuator_activation_close_time_
|
||||||
|
: this->actuator_activation_open_time_;
|
||||||
|
|
||||||
trig->trigger();
|
trig->trigger();
|
||||||
this->last_recompute_time_ = now;
|
this->last_recompute_time_ = now;
|
||||||
|
|
||||||
this->fsm_state_ = STATE_MOVING;
|
this->fsm_state_ = STATE_MOVING;
|
||||||
|
ESP_LOGD(TAG, "Transition to the moving state");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,46 +152,58 @@ void TimeBasedTiltCover::loop() {
|
||||||
auto travel_time = now - this->last_recompute_time_;
|
auto travel_time = now - this->last_recompute_time_;
|
||||||
this->last_recompute_time_ = now;
|
this->last_recompute_time_ = now;
|
||||||
|
|
||||||
|
// Actuator activation time support.
|
||||||
|
if (this->current_actuator_activation_time_ > 0) {
|
||||||
|
if (travel_time <= this->current_actuator_activation_time_) {
|
||||||
|
this->current_actuator_activation_time_ = this->current_actuator_activation_time_ - travel_time;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
travel_time = travel_time - this->current_actuator_activation_time_;
|
||||||
|
this->current_actuator_activation_time_ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float dir_factor = this->current_operation == COVER_OPERATION_CLOSING ? -1.0 : 1.0;
|
float dir_factor = this->current_operation == COVER_OPERATION_CLOSING ? -1.0 : 1.0;
|
||||||
auto inertia_time =
|
auto inertia_time =
|
||||||
this->current_operation == COVER_OPERATION_CLOSING ? this->inertia_close_time_ : this->inertia_open_time_;
|
this->current_operation == COVER_OPERATION_CLOSING ? this->inertia_close_time_ : this->inertia_open_time_;
|
||||||
|
|
||||||
if (inertia_time > 0 && this->inertia_ * dir_factor < 0.5f) { // inertia before movement
|
if (inertia_time > 0 && this->inertia_ * dir_factor < 0.5f) { // Inertia before movement
|
||||||
auto inertia_step = dir_factor * travel_time / inertia_time;
|
auto inertia_step = dir_factor * travel_time / inertia_time;
|
||||||
this->inertia_ += inertia_step;
|
this->inertia_ += inertia_step;
|
||||||
auto rest = this->inertia_ - clamp(this->inertia_, -0.5f, 0.5f);
|
auto inertia_rest = this->inertia_ - clamp(this->inertia_, -0.5f, 0.5f);
|
||||||
this->inertia_ = clamp(this->inertia_, -0.5f, 0.5f);
|
this->inertia_ = clamp(this->inertia_, -0.5f, 0.5f);
|
||||||
|
|
||||||
if (!rest)
|
if (!inertia_rest)
|
||||||
return; // the movement has not yet actually started
|
return; // The movement has not yet started.
|
||||||
travel_time = dir_factor * rest * inertia_time; // actual movement time taking inertia into account
|
travel_time = dir_factor * inertia_rest * inertia_time; // Actual movement time, taking inertia into account.
|
||||||
}
|
}
|
||||||
|
|
||||||
auto tilt_time =
|
auto tilt_time =
|
||||||
this->current_operation == COVER_OPERATION_CLOSING ? this->tilt_close_duration_ : this->tilt_open_duration_;
|
this->current_operation == COVER_OPERATION_CLOSING ? this->tilt_close_duration_ : this->tilt_open_duration_;
|
||||||
|
|
||||||
if (tilt_time > 0 && (this->tilt - 0.5f) * dir_factor < 0.5f) { // tilting before movement
|
if (tilt_time > 0 && (this->tilt - 0.5f) * dir_factor < 0.5f) { // Tilting before movement.
|
||||||
auto tilt_step = dir_factor * travel_time / tilt_time;
|
auto tilt_step = dir_factor * travel_time / tilt_time;
|
||||||
this->tilt += tilt_step;
|
this->tilt += tilt_step;
|
||||||
auto rest = this->tilt - 0.5f - clamp(this->tilt - 0.5f, -0.5f, 0.5f);
|
auto tilt_rest = this->tilt - 0.5f - clamp(this->tilt - 0.5f, -0.5f, 0.5f);
|
||||||
this->tilt = clamp(this->tilt, 0.0f, 1.0f);
|
this->tilt = clamp(this->tilt, 0.0f, 1.0f);
|
||||||
|
|
||||||
if (this->target_position_ == TARGET_NONE && this->is_at_target_tilt_()) { // only tilting w/o position change
|
if (this->target_position_ == TARGET_NONE && this->is_at_target_tilt_()) { // Only tilting w/o position change
|
||||||
this->last_recompute_time_ = now;
|
this->last_recompute_time_ = now;
|
||||||
this->target_tilt_ = TARGET_NONE;
|
this->target_tilt_ = TARGET_NONE;
|
||||||
this->last_publish_time_ = now;
|
this->last_publish_time_ = now;
|
||||||
|
this->tilt = this->round_position(this->tilt);
|
||||||
|
|
||||||
// If the cover is in extreme positions, run recalibration
|
// If the cover is in extreme positions, perform recalibration.
|
||||||
if (this->recalibration_time_ > 0 &&
|
if (this->current_recalibration_time_ > 0 && this->is_at_extreme_position_()) {
|
||||||
(((this->position == COVER_CLOSED && (tilt_time == 0 || this->tilt == COVER_CLOSED)) ||
|
|
||||||
(this->position == COVER_OPEN && (tilt_time == 0 || this->tilt == COVER_OPEN))))) {
|
|
||||||
this->fsm_state_ = STATE_CALIBRATING;
|
this->fsm_state_ = STATE_CALIBRATING;
|
||||||
this->publish_state(false);
|
this->publish_state(false);
|
||||||
|
ESP_LOGD(TAG, "Transition to the calibration state");
|
||||||
} else {
|
} else {
|
||||||
this->fsm_state_ = STATE_STOPPING;
|
this->fsm_state_ = STATE_STOPPING;
|
||||||
|
ESP_LOGD(TAG, "Transition to the stopping state");
|
||||||
}
|
}
|
||||||
|
|
||||||
return; // only tilting w/o position change so no need to recompute position
|
return; // Only tilting w/o position change, so there is no need to recompute the position.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (now - this->last_publish_time_ > ((tilt_time / 5) > 1000 ? 1000 : (tilt_time / 5))) {
|
if (now - this->last_publish_time_ > ((tilt_time / 5) > 1000 ? 1000 : (tilt_time / 5))) {
|
||||||
|
@ -163,15 +211,15 @@ void TimeBasedTiltCover::loop() {
|
||||||
this->last_publish_time_ = now;
|
this->last_publish_time_ = now;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rest)
|
if (!tilt_rest)
|
||||||
return; // the movement has not yet actually started
|
return; // The movement has not started yet.
|
||||||
|
|
||||||
travel_time = dir_factor * rest * tilt_time; // actual movement time taking tilt into account
|
travel_time = dir_factor * tilt_rest * tilt_time; // Actual movement time, taking tilt into account.
|
||||||
}
|
}
|
||||||
|
|
||||||
auto move_time = this->current_operation == COVER_OPERATION_CLOSING ? this->close_duration_ : this->open_duration_;
|
auto move_time = this->current_operation == COVER_OPERATION_CLOSING ? this->close_duration_ : this->open_duration_;
|
||||||
|
|
||||||
if (move_time > 0 && (this->position - 0.5f) * dir_factor < 0.5f) {
|
if ((this->position - 0.5f) * dir_factor < 0.5f) {
|
||||||
auto move_step = dir_factor * travel_time / move_time;
|
auto move_step = dir_factor * travel_time / move_time;
|
||||||
this->position += move_step;
|
this->position += move_step;
|
||||||
this->position = clamp(this->position, 0.0f, 1.0f);
|
this->position = clamp(this->position, 0.0f, 1.0f);
|
||||||
|
@ -181,15 +229,16 @@ void TimeBasedTiltCover::loop() {
|
||||||
this->last_recompute_time_ = now;
|
this->last_recompute_time_ = now;
|
||||||
this->target_position_ = TARGET_NONE;
|
this->target_position_ = TARGET_NONE;
|
||||||
this->last_publish_time_ = now;
|
this->last_publish_time_ = now;
|
||||||
|
this->position = this->round_position(this->position);
|
||||||
|
|
||||||
// If the cover is in extreme positions, run recalibration
|
// If the cover is in extreme positions, perform recalibration.
|
||||||
if (this->recalibration_time_ > 0 &&
|
if (this->current_recalibration_time_ > 0 && this->is_at_extreme_position_()) {
|
||||||
(((this->position == COVER_CLOSED && (tilt_time == 0 || this->tilt == COVER_CLOSED)) ||
|
|
||||||
(this->position == COVER_OPEN && (tilt_time == 0 || this->tilt == COVER_OPEN))))) {
|
|
||||||
this->fsm_state_ = STATE_CALIBRATING;
|
this->fsm_state_ = STATE_CALIBRATING;
|
||||||
this->publish_state(false);
|
this->publish_state(false);
|
||||||
|
ESP_LOGD(TAG, "Transition to the calibration state");
|
||||||
} else {
|
} else {
|
||||||
this->fsm_state_ = STATE_STOPPING;
|
this->fsm_state_ = STATE_STOPPING;
|
||||||
|
ESP_LOGD(TAG, "Transition to the stopping state");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,77 +264,51 @@ void TimeBasedTiltCover::control(const CoverCall &call) {
|
||||||
this->target_position_ = TARGET_NONE;
|
this->target_position_ = TARGET_NONE;
|
||||||
this->target_tilt_ = TARGET_NONE;
|
this->target_tilt_ = TARGET_NONE;
|
||||||
this->fsm_state_ = STATE_STOPPING;
|
this->fsm_state_ = STATE_STOPPING;
|
||||||
|
ESP_LOGD(TAG, "Transition to the stopping state");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (call.get_position().has_value() && call.get_tilt().has_value()) {
|
|
||||||
auto pos = *call.get_position();
|
|
||||||
auto til = *call.get_tilt();
|
|
||||||
|
|
||||||
if (this->round_position(pos) == this->round_position(this->position))
|
if (call.get_position().has_value() || call.get_tilt().has_value()) {
|
||||||
pos = TARGET_NONE;
|
if (call.get_position().has_value()) {
|
||||||
if (this->round_position(til) == this->round_position(this->tilt))
|
this->target_position_ = *call.get_position();
|
||||||
til = TARGET_NONE;
|
} else {
|
||||||
|
|
||||||
this->target_position_ = pos;
|
|
||||||
this->target_tilt_ = til;
|
|
||||||
|
|
||||||
if (this->fsm_state_ == STATE_MOVING) {
|
|
||||||
auto direction = COVER_OPERATION_IDLE;
|
|
||||||
if (this->target_position_ != TARGET_NONE && this->target_position_ != this->position) {
|
|
||||||
direction = this->compute_direction(this->target_position_, this->position);
|
|
||||||
} else if (this->target_tilt_ != TARGET_NONE && this->target_tilt_ != this->tilt) {
|
|
||||||
direction = this->compute_direction(this->target_tilt_, this->tilt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (direction != this->current_operation) {
|
|
||||||
this->fsm_state_ = STATE_STOPPING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (call.get_position().has_value()) {
|
|
||||||
auto pos = *call.get_position();
|
|
||||||
|
|
||||||
if (pos == COVER_CLOSED && this->position == COVER_CLOSED && this->tilt != COVER_CLOSED) {
|
|
||||||
pos = TARGET_NONE;
|
|
||||||
this->target_tilt_ = COVER_CLOSED;
|
|
||||||
} else if (pos == COVER_OPEN && this->position == COVER_OPEN && this->tilt != COVER_OPEN) {
|
|
||||||
pos = TARGET_NONE;
|
|
||||||
this->target_tilt_ = COVER_OPEN;
|
|
||||||
} else if (this->round_position(pos) == this->round_position(this->position)) {
|
|
||||||
pos = TARGET_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->target_position_ = pos;
|
|
||||||
|
|
||||||
if (this->fsm_state_ == STATE_MOVING) {
|
|
||||||
auto direction = COVER_OPERATION_IDLE;
|
|
||||||
if (this->target_position_ != TARGET_NONE && this->target_position_ != this->position) {
|
|
||||||
direction = this->compute_direction(this->target_position_, this->position);
|
|
||||||
this->target_tilt_ = TARGET_NONE; // unset previous target tilt
|
|
||||||
} else if (this->target_tilt_ != TARGET_NONE && this->target_tilt_ != this->tilt) {
|
|
||||||
direction = this->compute_direction(this->target_tilt_, this->tilt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (direction != this->current_operation) {
|
|
||||||
this->fsm_state_ = STATE_STOPPING;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (call.get_tilt().has_value()) {
|
|
||||||
auto til = *call.get_tilt();
|
|
||||||
if (this->round_position(til) == this->round_position(this->tilt)) {
|
|
||||||
til = TARGET_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
this->target_tilt_ = til;
|
|
||||||
|
|
||||||
if (this->fsm_state_ == STATE_MOVING) {
|
|
||||||
auto direction = COVER_OPERATION_IDLE;
|
|
||||||
if (this->target_tilt_ != TARGET_NONE && this->target_tilt_ != this->tilt) {
|
|
||||||
direction = this->compute_direction(this->target_tilt_, this->tilt);
|
|
||||||
this->target_position_ = TARGET_NONE;
|
this->target_position_ = TARGET_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (call.get_tilt().has_value()) {
|
||||||
|
this->target_tilt_ = *call.get_tilt();
|
||||||
|
} else {
|
||||||
|
this->target_tilt_ = TARGET_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->fsm_state_ == STATE_MOVING) {
|
||||||
|
auto direction = COVER_OPERATION_IDLE;
|
||||||
|
if (this->target_position_ != TARGET_NONE && this->target_position_ != this->position) {
|
||||||
|
direction = this->compute_direction(this->target_position_, this->position);
|
||||||
|
} else if (this->target_tilt_ != TARGET_NONE && this->target_tilt_ != this->tilt) {
|
||||||
|
direction = this->compute_direction(this->target_tilt_, this->tilt);
|
||||||
|
}
|
||||||
|
|
||||||
if (direction != this->current_operation) {
|
if (direction != this->current_operation) {
|
||||||
this->fsm_state_ = STATE_STOPPING;
|
this->fsm_state_ = STATE_STOPPING;
|
||||||
|
ESP_LOGD(TAG, "Transition to the stopping state");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this->fsm_state_ == STATE_CALIBRATING) {
|
||||||
|
if (this->target_position_ != TARGET_NONE) {
|
||||||
|
if ((this->position == COVER_CLOSED && this->target_position_ != COVER_CLOSED) ||
|
||||||
|
(this->position == COVER_OPEN && this->target_position_ != COVER_OPEN)) {
|
||||||
|
this->fsm_state_ = STATE_STOPPING;
|
||||||
|
ESP_LOGD(TAG, "Transition to the stopping state");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this->target_tilt_ != TARGET_NONE) {
|
||||||
|
if ((this->tilt == COVER_CLOSED && this->target_tilt_ != COVER_CLOSED) ||
|
||||||
|
(this->tilt == COVER_OPEN && this->target_tilt_ != COVER_OPEN)) {
|
||||||
|
this->fsm_state_ = STATE_STOPPING;
|
||||||
|
ESP_LOGD(TAG, "Transition to the stopping state");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -293,6 +316,7 @@ void TimeBasedTiltCover::control(const CoverCall &call) {
|
||||||
if (call.get_toggle().has_value()) {
|
if (call.get_toggle().has_value()) {
|
||||||
if (this->current_operation != COVER_OPERATION_IDLE) {
|
if (this->current_operation != COVER_OPERATION_IDLE) {
|
||||||
this->fsm_state_ = STATE_STOPPING;
|
this->fsm_state_ = STATE_STOPPING;
|
||||||
|
ESP_LOGD(TAG, "Transition to the stopping state");
|
||||||
this->target_position_ = TARGET_NONE;
|
this->target_position_ = TARGET_NONE;
|
||||||
this->target_tilt_ = TARGET_NONE;
|
this->target_tilt_ = TARGET_NONE;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -22,10 +22,22 @@ class TimeBasedTiltCover : public cover::Cover, public Component {
|
||||||
void set_tilt_open_duration(uint32_t tilt_open_duration) { this->tilt_open_duration_ = tilt_open_duration; }
|
void set_tilt_open_duration(uint32_t tilt_open_duration) { this->tilt_open_duration_ = tilt_open_duration; }
|
||||||
void set_tilt_close_duration(uint32_t tilt_close_duration) { this->tilt_close_duration_ = tilt_close_duration; }
|
void set_tilt_close_duration(uint32_t tilt_close_duration) { this->tilt_close_duration_ = tilt_close_duration; }
|
||||||
void set_interlock_wait_time(uint32_t interlock_wait_time) { this->interlock_wait_time_ = interlock_wait_time; }
|
void set_interlock_wait_time(uint32_t interlock_wait_time) { this->interlock_wait_time_ = interlock_wait_time; }
|
||||||
void set_recalibration_time(uint32_t recalibration_time) { this->recalibration_time_ = recalibration_time; }
|
void set_recalibration_open_time(uint32_t recalibration_time) { this->recalibration_open_time_ = recalibration_time; }
|
||||||
|
void set_recalibration_close_time(uint32_t recalibration_time) {
|
||||||
|
this->recalibration_close_time_ = recalibration_time;
|
||||||
|
}
|
||||||
void set_inertia_open_time(uint32_t inertia_time) { this->inertia_open_time_ = inertia_time; }
|
void set_inertia_open_time(uint32_t inertia_time) { this->inertia_open_time_ = inertia_time; }
|
||||||
void set_inertia_close_time(uint32_t inertia_time) { this->inertia_close_time_ = inertia_time; }
|
void set_inertia_close_time(uint32_t inertia_time) { this->inertia_close_time_ = inertia_time; }
|
||||||
|
void set_actuator_activation_open_time(uint32_t activation_time) {
|
||||||
|
this->actuator_activation_open_time_ = activation_time;
|
||||||
|
}
|
||||||
|
void set_actuator_activation_close_time(uint32_t activation_time) {
|
||||||
|
this->actuator_activation_close_time_ = activation_time;
|
||||||
|
}
|
||||||
cover::CoverOperation compute_direction(float target, float current) {
|
cover::CoverOperation compute_direction(float target, float current) {
|
||||||
|
if (target == current) {
|
||||||
|
return cover::COVER_OPERATION_IDLE;
|
||||||
|
}
|
||||||
return target < current ? cover::COVER_OPERATION_CLOSING : cover::COVER_OPERATION_OPENING;
|
return target < current ? cover::COVER_OPERATION_CLOSING : cover::COVER_OPERATION_OPENING;
|
||||||
};
|
};
|
||||||
float round_position(float pos) { return round(100 * pos) / 100; };
|
float round_position(float pos) { return round(100 * pos) / 100; };
|
||||||
|
@ -36,6 +48,7 @@ class TimeBasedTiltCover : public cover::Cover, public Component {
|
||||||
void control(const cover::CoverCall &call) override;
|
void control(const cover::CoverCall &call) override;
|
||||||
bool is_at_target_position_() const;
|
bool is_at_target_position_() const;
|
||||||
bool is_at_target_tilt_() const;
|
bool is_at_target_tilt_() const;
|
||||||
|
bool is_at_extreme_position_() const;
|
||||||
|
|
||||||
Trigger<> *open_trigger_{new Trigger<>()};
|
Trigger<> *open_trigger_{new Trigger<>()};
|
||||||
Trigger<> *close_trigger_{new Trigger<>()};
|
Trigger<> *close_trigger_{new Trigger<>()};
|
||||||
|
@ -48,9 +61,15 @@ class TimeBasedTiltCover : public cover::Cover, public Component {
|
||||||
uint32_t tilt_open_duration_;
|
uint32_t tilt_open_duration_;
|
||||||
|
|
||||||
uint32_t interlock_wait_time_;
|
uint32_t interlock_wait_time_;
|
||||||
uint32_t recalibration_time_;
|
uint32_t recalibration_open_time_;
|
||||||
|
uint32_t recalibration_close_time_;
|
||||||
uint32_t inertia_open_time_;
|
uint32_t inertia_open_time_;
|
||||||
uint32_t inertia_close_time_;
|
uint32_t inertia_close_time_;
|
||||||
|
uint32_t actuator_activation_open_time_;
|
||||||
|
uint32_t actuator_activation_close_time_;
|
||||||
|
|
||||||
|
uint32_t current_recalibration_time_;
|
||||||
|
uint32_t current_actuator_activation_time_;
|
||||||
|
|
||||||
const static float TARGET_NONE;
|
const static float TARGET_NONE;
|
||||||
enum State : uint8_t { STATE_IDLE, STATE_MOVING, STATE_STOPPING, STATE_CALIBRATING };
|
enum State : uint8_t { STATE_IDLE, STATE_MOVING, STATE_STOPPING, STATE_CALIBRATING };
|
||||||
|
|
Loading…
Reference in a new issue