Add new cover triggers: on_opening, on_closing, on_idle, on_opened

Co-authored-by: clydebarrow <2366188+clydebarrow@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-01-23 02:58:20 +00:00
parent 6f2ca4c2a7
commit 0d63c755b7
4 changed files with 135 additions and 2 deletions
+45 -2
View File
@@ -9,7 +9,11 @@ from esphome.const import (
CONF_ICON,
CONF_ID,
CONF_MQTT_ID,
CONF_ON_CLOSING,
CONF_ON_IDLE,
CONF_ON_OPEN,
CONF_ON_OPENED,
CONF_ON_OPENING,
CONF_POSITION,
CONF_POSITION_COMMAND_TOPIC,
CONF_POSITION_STATE_TOPIC,
@@ -86,9 +90,13 @@ CoverIsClosedCondition = cover_ns.class_("CoverIsClosedCondition", Condition)
# Triggers
CoverOpenTrigger = cover_ns.class_("CoverOpenTrigger", automation.Trigger.template())
CoverOpenedTrigger = cover_ns.class_("CoverOpenedTrigger", automation.Trigger.template())
CoverClosedTrigger = cover_ns.class_(
"CoverClosedTrigger", automation.Trigger.template()
)
CoverOpeningTrigger = cover_ns.class_("CoverOpeningTrigger", automation.Trigger.template())
CoverClosingTrigger = cover_ns.class_("CoverClosingTrigger", automation.Trigger.template())
CoverIdleTrigger = cover_ns.class_("CoverIdleTrigger", automation.Trigger.template())
CONF_ON_CLOSED = "on_closed"
@@ -111,9 +119,17 @@ _COVER_SCHEMA = (
cv.Optional(CONF_TILT_STATE_TOPIC): cv.All(
cv.requires_component("mqtt"), cv.subscribe_topic
),
cv.Optional(CONF_ON_OPEN): automation.validate_automation(
cv.Optional(CONF_ON_OPEN): cv.All(
cv.deprecated(CONF_ON_OPENED, "2026.2.0"),
automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CoverOpenTrigger),
}
),
),
cv.Optional(CONF_ON_OPENED): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CoverOpenTrigger),
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CoverOpenedTrigger),
}
),
cv.Optional(CONF_ON_CLOSED): automation.validate_automation(
@@ -121,6 +137,21 @@ _COVER_SCHEMA = (
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CoverClosedTrigger),
}
),
cv.Optional(CONF_ON_OPENING): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CoverOpeningTrigger),
}
),
cv.Optional(CONF_ON_CLOSING): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CoverClosingTrigger),
}
),
cv.Optional(CONF_ON_IDLE): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(CoverIdleTrigger),
}
),
}
)
)
@@ -160,9 +191,21 @@ async def setup_cover_core_(var, config):
for conf in config.get(CONF_ON_OPEN, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(trigger, [], conf)
for conf in config.get(CONF_ON_OPENED, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(trigger, [], conf)
for conf in config.get(CONF_ON_CLOSED, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(trigger, [], conf)
for conf in config.get(CONF_ON_OPENING, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(trigger, [], conf)
for conf in config.get(CONF_ON_CLOSING, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(trigger, [], conf)
for conf in config.get(CONF_ON_IDLE, []):
trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var)
await automation.build_automation(trigger, [], conf)
if (mqtt_id := config.get(CONF_MQTT_ID)) is not None:
mqtt_ = cg.new_Pvariable(mqtt_id, var)
+59
View File
@@ -119,6 +119,17 @@ class CoverOpenTrigger : public Trigger<> {
}
};
class CoverOpenedTrigger : public Trigger<> {
public:
CoverOpenedTrigger(Cover *a_cover) {
a_cover->add_on_state_callback([this, a_cover]() {
if (a_cover->is_fully_open()) {
this->trigger();
}
});
}
};
class CoverClosedTrigger : public Trigger<> {
public:
CoverClosedTrigger(Cover *a_cover) {
@@ -130,4 +141,52 @@ class CoverClosedTrigger : public Trigger<> {
}
};
class CoverOpeningTrigger : public Trigger<> {
public:
CoverOpeningTrigger(Cover *a_cover) {
a_cover->add_on_state_callback([this, a_cover]() {
auto current_op = a_cover->current_operation;
if (current_op == COVER_OPERATION_OPENING && this->last_operation_ != COVER_OPERATION_OPENING) {
this->trigger();
}
this->last_operation_ = current_op;
});
}
protected:
CoverOperation last_operation_{COVER_OPERATION_IDLE};
};
class CoverClosingTrigger : public Trigger<> {
public:
CoverClosingTrigger(Cover *a_cover) {
a_cover->add_on_state_callback([this, a_cover]() {
auto current_op = a_cover->current_operation;
if (current_op == COVER_OPERATION_CLOSING && this->last_operation_ != COVER_OPERATION_CLOSING) {
this->trigger();
}
this->last_operation_ = current_op;
});
}
protected:
CoverOperation last_operation_{COVER_OPERATION_IDLE};
};
class CoverIdleTrigger : public Trigger<> {
public:
CoverIdleTrigger(Cover *a_cover) {
a_cover->add_on_state_callback([this, a_cover]() {
auto current_op = a_cover->current_operation;
if (current_op == COVER_OPERATION_IDLE && this->last_operation_ != COVER_OPERATION_IDLE) {
this->trigger();
}
this->last_operation_ = current_op;
});
}
protected:
CoverOperation last_operation_{COVER_OPERATION_IDLE};
};
} // namespace esphome::cover
+4
View File
@@ -703,6 +703,10 @@ CONF_ON_LOOP = "on_loop"
CONF_ON_MESSAGE = "on_message"
CONF_ON_MULTI_CLICK = "on_multi_click"
CONF_ON_OPEN = "on_open"
CONF_ON_OPENED = "on_opened"
CONF_ON_OPENING = "on_opening"
CONF_ON_CLOSING = "on_closing"
CONF_ON_IDLE = "on_idle"
CONF_ON_OSCILLATING_SET = "on_oscillating_set"
CONF_ON_PRESET_SET = "on_preset_set"
CONF_ON_PRESS = "on_press"
@@ -245,6 +245,33 @@ cover:
stop_action:
- logger.log: stop_action
optimistic: true
- platform: template
name: "Template Cover with Triggers"
id: template_cover_with_triggers
lambda: |-
if (id(some_binary_sensor).state) {
return COVER_OPEN;
}
return COVER_CLOSED;
open_action:
- logger.log: open_action
close_action:
- logger.log: close_action
stop_action:
- logger.log: stop_action
optimistic: true
on_open:
- logger.log: "Cover on_open (deprecated)"
on_opened:
- logger.log: "Cover fully opened"
on_closed:
- logger.log: "Cover fully closed"
on_opening:
- logger.log: "Cover started opening"
on_closing:
- logger.log: "Cover started closing"
on_idle:
- logger.log: "Cover stopped moving"
number:
- platform: template