diff --git a/esphome/components/light/base_light_effects.h b/esphome/components/light/base_light_effects.h index d6d930e9d4..775ee363af 100644 --- a/esphome/components/light/base_light_effects.h +++ b/esphome/components/light/base_light_effects.h @@ -11,6 +11,40 @@ inline static float random_cubic_float() { return r * r * r; } +/// Pulse effect. +class PulseLightEffect : public LightEffect { + public: + explicit PulseLightEffect(const std::string &name) : LightEffect(name) {} + + void apply() override { + const uint32_t now = millis(); + if (now - this->last_color_change_ < this->update_interval_) { + return; + } + auto call = this->state_->turn_on(); + float out = this->on_ ? 1.0 : 0.0; + call.set_brightness_if_supported(out); + this->on_ = !this->on_; + call.set_transition_length_if_supported(this->transition_length_); + // don't tell HA every change + call.set_publish(false); + call.set_save(false); + call.perform(); + + this->last_color_change_ = now; + } + + void set_transition_length(uint32_t transition_length) { this->transition_length_ = transition_length; } + + void set_update_interval(uint32_t update_interval) { this->update_interval_ = update_interval; } + + protected: + bool on_ = false; + uint32_t last_color_change_{0}; + uint32_t transition_length_{}; + uint32_t update_interval_{}; +}; + /// Random effect. Sets random colors every 10 seconds and slowly transitions between them. class RandomLightEffect : public LightEffect { public: @@ -22,10 +56,14 @@ class RandomLightEffect : public LightEffect { return; } auto call = this->state_->turn_on(); - call.set_red_if_supported(random_float()); - call.set_green_if_supported(random_float()); - call.set_blue_if_supported(random_float()); - call.set_white_if_supported(random_float()); + if (this->state_->get_traits().get_supports_rgb()) { + call.set_red_if_supported(random_float()); + call.set_green_if_supported(random_float()); + call.set_blue_if_supported(random_float()); + call.set_white_if_supported(random_float()); + } else { + call.set_brightness_if_supported(random_float()); + } call.set_color_temperature_if_supported(random_float()); call.set_transition_length_if_supported(this->transition_length_); call.set_publish(true); diff --git a/esphome/components/light/effects.py b/esphome/components/light/effects.py index 9f017de98b..08a78d90ed 100644 --- a/esphome/components/light/effects.py +++ b/esphome/components/light/effects.py @@ -26,6 +26,7 @@ from esphome.const import ( from esphome.util import Registry from .types import ( LambdaLightEffect, + PulseLightEffect, RandomLightEffect, StrobeLightEffect, StrobeLightEffectColor, @@ -152,7 +153,27 @@ def automation_effect_to_code(config, effect_id): yield var -@register_rgb_effect( +@register_monochromatic_effect( + "pulse", + PulseLightEffect, + "Pulse", + { + cv.Optional( + CONF_TRANSITION_LENGTH, default="1s" + ): cv.positive_time_period_milliseconds, + cv.Optional( + CONF_UPDATE_INTERVAL, default="1s" + ): cv.positive_time_period_milliseconds, + }, +) +def pulse_effect_to_code(config, effect_id): + effect = cg.new_Pvariable(effect_id, config[CONF_NAME]) + cg.add(effect.set_transition_length(config[CONF_TRANSITION_LENGTH])) + cg.add(effect.set_update_interval(config[CONF_UPDATE_INTERVAL])) + yield effect + + +@register_monochromatic_effect( "random", RandomLightEffect, "Random", diff --git a/esphome/components/light/types.py b/esphome/components/light/types.py index 4bca266b67..7c96cda7b1 100644 --- a/esphome/components/light/types.py +++ b/esphome/components/light/types.py @@ -31,6 +31,7 @@ LightTurnOffTrigger = light_ns.class_( # Effects LightEffect = light_ns.class_("LightEffect") +PulseLightEffect = light_ns.class_("PulseLightEffect", LightEffect) RandomLightEffect = light_ns.class_("RandomLightEffect", LightEffect) LambdaLightEffect = light_ns.class_("LambdaLightEffect", LightEffect) AutomationLightEffect = light_ns.class_("AutomationLightEffect", LightEffect)