Refactorings, query door status at end of an open/close operation in case the status is not received

This commit is contained in:
Marius Muja 2024-01-11 15:10:51 -08:00
parent 65dfae4d0a
commit 1274ef9172
5 changed files with 81 additions and 57 deletions

View File

@ -264,4 +264,4 @@ button:
on_press: on_press:
then: then:
lambda: !lambda |- lambda: !lambda |-
id($id_prefix).toggle_door(); id($id_prefix).door_toggle();

View File

@ -233,4 +233,4 @@ button:
on_press: on_press:
then: then:
lambda: !lambda |- lambda: !lambda |-
id($id_prefix).toggle_door(); id($id_prefix).door_toggle();

View File

@ -70,17 +70,17 @@ namespace ratgdo {
void RATGDOCover::control(const CoverCall& call) void RATGDOCover::control(const CoverCall& call)
{ {
if (call.get_stop()) { if (call.get_stop()) {
this->parent_->stop_door(); this->parent_->door_stop();
} }
if (call.get_toggle()) { if (call.get_toggle()) {
this->parent_->toggle_door(); this->parent_->door_toggle();
} }
if (call.get_position().has_value()) { if (call.get_position().has_value()) {
auto pos = *call.get_position(); auto pos = *call.get_position();
if (pos == COVER_OPEN) { if (pos == COVER_OPEN) {
this->parent_->open_door(); this->parent_->door_open();
} else if (pos == COVER_CLOSED) { } else if (pos == COVER_CLOSED) {
this->parent_->close_door(); this->parent_->door_close();
} else { } else {
this->parent_->door_move_to_position(pos); this->parent_->door_move_to_position(pos);
} }

View File

@ -152,6 +152,7 @@ namespace ratgdo {
this->door_position = 0.5; // best guess this->door_position = 0.5; // best guess
} }
this->cancel_position_sync_callbacks(); this->cancel_position_sync_callbacks();
cancel_timeout("door_query_state");
} else if (door_state == DoorState::OPEN) { } else if (door_state == DoorState::OPEN) {
this->door_position = 1.0; this->door_position = 1.0;
this->cancel_position_sync_callbacks(); this->cancel_position_sync_callbacks();
@ -377,16 +378,23 @@ namespace ratgdo {
this->protocol_->sync(); this->protocol_->sync();
} }
void RATGDOComponent::open_door() void RATGDOComponent::door_open()
{ {
if (*this->door_state == DoorState::OPENING) { if (*this->door_state == DoorState::OPENING) {
return; // gets ignored by opener return; // gets ignored by opener
} }
this->protocol_->door_action(DoorAction::OPEN); this->door_action(DoorAction::OPEN);
// query state in case we don't get a status message
set_timeout("door_query_state", (*this->opening_duration + 2)*1000, [=]() {
if (*this->door_state != DoorState::OPEN && *this->door_state != DoorState::STOPPED) {
this->query_status();
}
});
} }
void RATGDOComponent::close_door() void RATGDOComponent::door_close()
{ {
if (*this->door_state == DoorState::CLOSING) { if (*this->door_state == DoorState::CLOSING) {
return; // gets ignored by opener return; // gets ignored by opener
@ -394,10 +402,10 @@ namespace ratgdo {
if (*this->door_state == DoorState::OPENING) { if (*this->door_state == DoorState::OPENING) {
// have to stop door first, otherwise close command is ignored // have to stop door first, otherwise close command is ignored
this->protocol_->door_action(DoorAction::STOP); this->door_action(DoorAction::STOP);
this->door_state_received.then([=](DoorState s) { this->door_state_received.then([=](DoorState s) {
if (s == DoorState::STOPPED) { if (s == DoorState::STOPPED) {
this->protocol_->door_action(DoorAction::CLOSE); this->door_action(DoorAction::CLOSE);
} else { } else {
ESP_LOGW(TAG, "Door did not stop, ignoring close command"); ESP_LOGW(TAG, "Door did not stop, ignoring close command");
} }
@ -405,27 +413,66 @@ namespace ratgdo {
return; return;
} }
this->protocol_->door_action(DoorAction::CLOSE); this->door_action(DoorAction::CLOSE);
// query state in case we don't get a status message
set_timeout("door_query_state", (*this->closing_duration + 2)*1000, [=]() {
if (*this->door_state != DoorState::CLOSED && *this->door_state != DoorState::STOPPED) {
this->query_status();
}
});
} }
void RATGDOComponent::stop_door() void RATGDOComponent::door_stop()
{ {
if (*this->door_state != DoorState::OPENING && *this->door_state != DoorState::CLOSING) { if (*this->door_state != DoorState::OPENING && *this->door_state != DoorState::CLOSING) {
ESP_LOGW(TAG, "The door is not moving."); ESP_LOGW(TAG, "The door is not moving.");
return; return;
} }
this->protocol_->door_action(DoorAction::STOP); this->door_action(DoorAction::STOP);
} }
void RATGDOComponent::toggle_door() void RATGDOComponent::door_toggle()
{ {
this->protocol_->door_action(DoorAction::TOGGLE); this->door_action(DoorAction::TOGGLE);
}
void RATGDOComponent::door_action(DoorAction action)
{
this->protocol_->door_action(action);
}
void RATGDOComponent::ensure_door_action(DoorAction action, uint32_t delay)
{
if (action == DoorAction::TOGGLE) {
ESP_LOGW(TAG, "It's not recommended to use ensure_door_action with non-idempotent commands such as DOOR_TOGGLE");
}
auto prev_door_state = *this->door_state;
this->door_state_received.then([=](DoorState s) {
if ((action == DoorAction::STOP) && (s != DoorState::STOPPED) && !(prev_door_state == DoorState::OPENING && s == DoorState::OPEN) && !(prev_door_state == DoorState::CLOSING && s == DoorState::CLOSED)) {
return;
}
if (action == DoorAction::OPEN && !(s == DoorState::OPENING || s == DoorState::OPEN)) {
return;
}
if (action == DoorAction::CLOSE && !(s == DoorState::CLOSED || s == DoorState::CLOSING)) {
return;
}
ESP_LOG1(TAG, "Received door status, cancel door command retry");
cancel_timeout("door_command_retry");
});
this->door_action(action);
ESP_LOG1(TAG, "Ensure door command, setup door command retry");
set_timeout("door_command_retry", delay, [=]() {
this->ensure_door_action(action);
});
} }
void RATGDOComponent::door_move_to_position(float position) void RATGDOComponent::door_move_to_position(float position)
{ {
if (*this->door_state == DoorState::OPENING || *this->door_state == DoorState::CLOSING) { if (*this->door_state == DoorState::OPENING || *this->door_state == DoorState::CLOSING) {
this->protocol_->door_action(DoorAction::STOP); this->door_action(DoorAction::STOP);
this->door_state_received.then([=](DoorState s) { this->door_state_received.then([=](DoorState s) {
if (s == DoorState::STOPPED) { if (s == DoorState::STOPPED) {
this->door_move_to_position(position); this->door_move_to_position(position);
@ -450,7 +497,7 @@ namespace ratgdo {
this->door_move_delta = delta; this->door_move_delta = delta;
ESP_LOGD(TAG, "Moving to position %.2f in %.1fs", position, operation_time / 1000.0); ESP_LOGD(TAG, "Moving to position %.2f in %.1fs", position, operation_time / 1000.0);
this->protocol_->door_action(delta > 0 ? DoorAction::OPEN : DoorAction::CLOSE); this->door_action(delta > 0 ? DoorAction::OPEN : DoorAction::CLOSE);
set_timeout("move_to_position", operation_time, [=] { set_timeout("move_to_position", operation_time, [=] {
this->ensure_door_action(DoorAction::STOP); this->ensure_door_action(DoorAction::STOP);
}); });
@ -469,32 +516,6 @@ namespace ratgdo {
} }
} }
void RATGDOComponent::ensure_door_action(DoorAction action, uint32_t delay)
{
if (action == DoorAction::TOGGLE) {
ESP_LOGW(TAG, "It's not recommended to use ensure_door_action with non-idempotent commands such as DOOR_TOGGLE");
}
auto prev_door_state = *this->door_state;
this->door_state_received.then([=](DoorState s) {
if ((action == DoorAction::STOP) && (s != DoorState::STOPPED) && !(prev_door_state == DoorState::OPENING && s == DoorState::OPEN) && !(prev_door_state == DoorState::CLOSING && s == DoorState::CLOSED)) {
return;
}
if (action == DoorAction::OPEN && !(s == DoorState::OPENING || s == DoorState::OPEN)) {
return;
}
if (action == DoorAction::CLOSE && !(s == DoorState::CLOSED || s == DoorState::CLOSING)) {
return;
}
ESP_LOG1(TAG, "Received door status, cancel door command retry");
cancel_timeout("door_command_retry");
});
this->protocol_->door_action(action);
ESP_LOG1(TAG, "Ensure door command, setup door command retry");
set_timeout("door_command_retry", delay, [=]() {
this->ensure_door_action(action);
});
}
void RATGDOComponent::light_on() void RATGDOComponent::light_on()
{ {
@ -508,12 +529,17 @@ namespace ratgdo {
this->protocol_->light_action(LightAction::OFF); this->protocol_->light_action(LightAction::OFF);
} }
void RATGDOComponent::toggle_light() void RATGDOComponent::light_toggle()
{ {
this->light_state = light_state_toggle(*this->light_state); this->light_state = light_state_toggle(*this->light_state);
this->protocol_->light_action(LightAction::TOGGLE); this->protocol_->light_action(LightAction::TOGGLE);
} }
LightState RATGDOComponent::get_light_state() const
{
return *this->light_state;
}
// Lock functions // Lock functions
void RATGDOComponent::lock() void RATGDOComponent::lock()
{ {
@ -527,17 +553,12 @@ namespace ratgdo {
this->protocol_->lock_action(LockAction::UNLOCK); this->protocol_->lock_action(LockAction::UNLOCK);
} }
void RATGDOComponent::toggle_lock() void RATGDOComponent::lock_toggle()
{ {
this->lock_state = lock_state_toggle(*this->lock_state); this->lock_state = lock_state_toggle(*this->lock_state);
this->protocol_->lock_action(LockAction::TOGGLE); this->protocol_->lock_action(LockAction::TOGGLE);
} }
LightState RATGDOComponent::get_light_state() const
{
return *this->light_state;
}
// Learn functions // Learn functions
void RATGDOComponent::activate_learn() void RATGDOComponent::activate_learn()
{ {

View File

@ -108,11 +108,13 @@ namespace ratgdo {
void received(const PairedDeviceCount pdc); void received(const PairedDeviceCount pdc);
// door // door
void door_toggle();
void door_open();
void door_close();
void door_stop();
void door_action(DoorAction action);
void ensure_door_action(DoorAction action, uint32_t delay = 1500); void ensure_door_action(DoorAction action, uint32_t delay = 1500);
void toggle_door();
void open_door();
void close_door();
void stop_door();
void door_move_to_position(float position); void door_move_to_position(float position);
void set_door_position(float door_position) { this->door_position = door_position; } void set_door_position(float door_position) { this->door_position = door_position; }
void set_opening_duration(float duration); void set_opening_duration(float duration);
@ -121,14 +123,15 @@ namespace ratgdo {
void door_position_update(); void door_position_update();
void cancel_position_sync_callbacks(); void cancel_position_sync_callbacks();
// light // light
void toggle_light(); void light_toggle();
void light_on(); void light_on();
void light_off(); void light_off();
LightState get_light_state() const; LightState get_light_state() const;
// lock // lock
void toggle_lock(); void lock_toggle();
void lock(); void lock();
void unlock(); void unlock();