diff --git a/esphome/components/fan/__init__.py b/esphome/components/fan/__init__.py index 10e38682e7..43d9297f96 100644 --- a/esphome/components/fan/__init__.py +++ b/esphome/components/fan/__init__.py @@ -14,6 +14,9 @@ from esphome.const import ( CONF_SPEED_COMMAND_TOPIC, CONF_SPEED_STATE_TOPIC, CONF_NAME, + CONF_ON_TURN_OFF, + CONF_ON_TURN_ON, + CONF_TRIGGER_ID, ) from esphome.core import CORE, coroutine, coroutine_with_priority @@ -28,6 +31,9 @@ TurnOnAction = fan_ns.class_("TurnOnAction", automation.Action) TurnOffAction = fan_ns.class_("TurnOffAction", automation.Action) ToggleAction = fan_ns.class_("ToggleAction", automation.Action) +FanTurnOnTrigger = fan_ns.class_("FanTurnOnTrigger", automation.Trigger.template()) +FanTurnOffTrigger = fan_ns.class_("FanTurnOffTrigger", automation.Trigger.template()) + FAN_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend( { cv.GenerateID(): cv.declare_id(FanState), @@ -44,6 +50,16 @@ FAN_SCHEMA = cv.MQTT_COMMAND_COMPONENT_SCHEMA.extend( cv.Optional(CONF_SPEED_COMMAND_TOPIC): cv.All( cv.requires_component("mqtt"), cv.subscribe_topic ), + cv.Optional(CONF_ON_TURN_ON): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FanTurnOnTrigger), + } + ), + cv.Optional(CONF_ON_TURN_OFF): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(FanTurnOffTrigger), + } + ), } ) @@ -77,6 +93,13 @@ def setup_fan_core_(var, config): mqtt_.set_custom_speed_command_topic(config[CONF_SPEED_COMMAND_TOPIC]) ) + for conf in config.get(CONF_ON_TURN_ON, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + yield automation.build_automation(trigger, [], conf) + for conf in config.get(CONF_ON_TURN_OFF, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + yield automation.build_automation(trigger, [], conf) + @coroutine def register_fan(var, config): diff --git a/esphome/components/fan/automation.h b/esphome/components/fan/automation.h index 25c92075ba..fbfc71c720 100644 --- a/esphome/components/fan/automation.h +++ b/esphome/components/fan/automation.h @@ -46,5 +46,41 @@ template class ToggleAction : public Action { FanState *state_; }; +class FanTurnOnTrigger : public Trigger<> { + public: + FanTurnOnTrigger(FanState *state) { + state->add_on_state_callback([this, state]() { + auto is_on = state->state; + auto should_trigger = is_on && !this->last_on_; + this->last_on_ = is_on; + if (should_trigger) { + this->trigger(); + } + }); + this->last_on_ = state->state; + } + + protected: + bool last_on_; +}; + +class FanTurnOffTrigger : public Trigger<> { + public: + FanTurnOffTrigger(FanState *state) { + state->add_on_state_callback([this, state]() { + auto is_on = state->state; + auto should_trigger = !is_on && this->last_on_; + this->last_on_ = is_on; + if (should_trigger) { + this->trigger(); + } + }); + this->last_on_ = state->state; + } + + protected: + bool last_on_; +}; + } // namespace fan } // namespace esphome