From c5b1a8eb81c4187c3c0f7ca4da40232425845113 Mon Sep 17 00:00:00 2001 From: PaoloTK <60204407+PaoloTK@users.noreply.github.com> Date: Tue, 13 Aug 2024 23:29:55 +0200 Subject: [PATCH] Add min and max brightness parameters for Light dim_relative Action (#6971) --- esphome/components/light/automation.h | 17 ++++++++++++++- esphome/components/light/automation.py | 21 +++++++++++++++++++ esphome/components/light/types.py | 7 +++++++ esphome/const.py | 2 ++ tests/components/light/test.esp32-ard.yaml | 2 ++ tests/components/light/test.esp32-c3-ard.yaml | 2 ++ tests/components/light/test.esp32-c3-idf.yaml | 2 ++ tests/components/light/test.esp32-idf.yaml | 2 ++ tests/components/light/test.esp8266-ard.yaml | 2 ++ tests/components/light/test.rp2040-ard.yaml | 2 ++ 10 files changed, 58 insertions(+), 1 deletion(-) diff --git a/esphome/components/light/automation.h b/esphome/components/light/automation.h index b63fc93dc5..6e055741da 100644 --- a/esphome/components/light/automation.h +++ b/esphome/components/light/automation.h @@ -7,6 +7,8 @@ namespace esphome { namespace light { +enum class LimitMode { CLAMP, DO_NOTHING }; + template class ToggleAction : public Action { public: explicit ToggleAction(LightState *state) : state_(state) {} @@ -77,7 +79,10 @@ template class DimRelativeAction : public Action { float rel = this->relative_brightness_.value(x...); float cur; this->parent_->remote_values.as_brightness(&cur); - float new_brightness = clamp(cur + rel, 0.0f, 1.0f); + if ((limit_mode_ == LimitMode::DO_NOTHING) && ((cur < min_brightness_) || (cur > max_brightness_))) { + return; + } + float new_brightness = clamp(cur + rel, min_brightness_, max_brightness_); call.set_state(new_brightness != 0.0f); call.set_brightness(new_brightness); @@ -85,8 +90,18 @@ template class DimRelativeAction : public Action { call.perform(); } + void set_min_max_brightness(float min, float max) { + this->min_brightness_ = min; + this->max_brightness_ = max; + } + + void set_limit_mode(LimitMode limit_mode) { this->limit_mode_ = limit_mode; } + protected: LightState *parent_; + float min_brightness_{0.0}; + float max_brightness_{1.0}; + LimitMode limit_mode_{LimitMode::CLAMP}; }; template class LightIsOnCondition : public Condition { diff --git a/esphome/components/light/automation.py b/esphome/components/light/automation.py index cfba273565..ec0375f54a 100644 --- a/esphome/components/light/automation.py +++ b/esphome/components/light/automation.py @@ -19,10 +19,15 @@ from esphome.const import ( CONF_WARM_WHITE, CONF_RANGE_FROM, CONF_RANGE_TO, + CONF_BRIGHTNESS_LIMITS, + CONF_LIMIT_MODE, + CONF_MIN_BRIGHTNESS, + CONF_MAX_BRIGHTNESS, ) from .types import ( ColorMode, COLOR_MODES, + LIMIT_MODES, DimRelativeAction, ToggleAction, LightState, @@ -167,6 +172,15 @@ LIGHT_DIM_RELATIVE_ACTION_SCHEMA = cv.Schema( cv.Optional(CONF_TRANSITION_LENGTH): cv.templatable( cv.positive_time_period_milliseconds ), + cv.Optional(CONF_BRIGHTNESS_LIMITS): cv.Schema( + { + cv.Optional(CONF_MIN_BRIGHTNESS, default="0%"): cv.percentage, + cv.Optional(CONF_MAX_BRIGHTNESS, default="100%"): cv.percentage, + cv.Optional(CONF_LIMIT_MODE, default="CLAMP"): cv.enum( + LIMIT_MODES, upper=True, space="_" + ), + } + ), } ) @@ -182,6 +196,13 @@ async def light_dim_relative_to_code(config, action_id, template_arg, args): if CONF_TRANSITION_LENGTH in config: templ = await cg.templatable(config[CONF_TRANSITION_LENGTH], args, cg.uint32) cg.add(var.set_transition_length(templ)) + if conf := config.get(CONF_BRIGHTNESS_LIMITS): + cg.add( + var.set_min_max_brightness( + conf[CONF_MIN_BRIGHTNESS], conf[CONF_MAX_BRIGHTNESS] + ) + ) + cg.add(var.set_limit_mode(conf[CONF_LIMIT_MODE])) return var diff --git a/esphome/components/light/types.py b/esphome/components/light/types.py index a453debd94..64483bcc9c 100644 --- a/esphome/components/light/types.py +++ b/esphome/components/light/types.py @@ -26,6 +26,13 @@ COLOR_MODES = { "RGB_COLD_WARM_WHITE": ColorMode.RGB_COLD_WARM_WHITE, } +# Limit modes +LimitMode = light_ns.enum("LimitMode", is_class=True) +LIMIT_MODES = { + "CLAMP": LimitMode.CLAMP, + "DO_NOTHING": LimitMode.DO_NOTHING, +} + # Actions ToggleAction = light_ns.class_("ToggleAction", automation.Action) LightControlAction = light_ns.class_("LightControlAction", automation.Action) diff --git a/esphome/const.py b/esphome/const.py index 55f1c23b40..37f20796b5 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -95,6 +95,7 @@ CONF_BOARD_FLASH_MODE = "board_flash_mode" CONF_BORDER = "border" CONF_BRANCH = "branch" CONF_BRIGHTNESS = "brightness" +CONF_BRIGHTNESS_LIMITS = "brightness_limits" CONF_BROKER = "broker" CONF_BSSID = "bssid" CONF_BUFFER_SIZE = "buffer_size" @@ -429,6 +430,7 @@ CONF_LIGHT = "light" CONF_LIGHT_ID = "light_id" CONF_LIGHTNING_ENERGY = "lightning_energy" CONF_LIGHTNING_THRESHOLD = "lightning_threshold" +CONF_LIMIT_MODE = "limit_mode" CONF_LINE_THICKNESS = "line_thickness" CONF_LINE_TYPE = "line_type" CONF_LOADED_INTEGRATIONS = "loaded_integrations" diff --git a/tests/components/light/test.esp32-ard.yaml b/tests/components/light/test.esp32-ard.yaml index 7e5718d8d4..1d0b4cd8f0 100644 --- a/tests/components/light/test.esp32-ard.yaml +++ b/tests/components/light/test.esp32-ard.yaml @@ -15,6 +15,8 @@ esphome: - light.dim_relative: id: test_monochromatic_light relative_brightness: 5% + brightness_limits: + max_brightness: 90% output: - platform: gpio diff --git a/tests/components/light/test.esp32-c3-ard.yaml b/tests/components/light/test.esp32-c3-ard.yaml index 8e1709838a..79171805a6 100644 --- a/tests/components/light/test.esp32-c3-ard.yaml +++ b/tests/components/light/test.esp32-c3-ard.yaml @@ -15,6 +15,8 @@ esphome: - light.dim_relative: id: test_monochromatic_light relative_brightness: 5% + brightness_limits: + max_brightness: 90% output: - platform: gpio diff --git a/tests/components/light/test.esp32-c3-idf.yaml b/tests/components/light/test.esp32-c3-idf.yaml index 8e1709838a..79171805a6 100644 --- a/tests/components/light/test.esp32-c3-idf.yaml +++ b/tests/components/light/test.esp32-c3-idf.yaml @@ -15,6 +15,8 @@ esphome: - light.dim_relative: id: test_monochromatic_light relative_brightness: 5% + brightness_limits: + max_brightness: 90% output: - platform: gpio diff --git a/tests/components/light/test.esp32-idf.yaml b/tests/components/light/test.esp32-idf.yaml index 7e5718d8d4..1d0b4cd8f0 100644 --- a/tests/components/light/test.esp32-idf.yaml +++ b/tests/components/light/test.esp32-idf.yaml @@ -15,6 +15,8 @@ esphome: - light.dim_relative: id: test_monochromatic_light relative_brightness: 5% + brightness_limits: + max_brightness: 90% output: - platform: gpio diff --git a/tests/components/light/test.esp8266-ard.yaml b/tests/components/light/test.esp8266-ard.yaml index 4611fb374a..555e1a1b67 100644 --- a/tests/components/light/test.esp8266-ard.yaml +++ b/tests/components/light/test.esp8266-ard.yaml @@ -15,6 +15,8 @@ esphome: - light.dim_relative: id: test_monochromatic_light relative_brightness: 5% + brightness_limits: + max_brightness: 90% output: - platform: gpio diff --git a/tests/components/light/test.rp2040-ard.yaml b/tests/components/light/test.rp2040-ard.yaml index 0215a17e71..a509bc85c9 100644 --- a/tests/components/light/test.rp2040-ard.yaml +++ b/tests/components/light/test.rp2040-ard.yaml @@ -15,6 +15,8 @@ esphome: - light.dim_relative: id: test_monochromatic_light relative_brightness: 5% + brightness_limits: + max_brightness: 90% output: - platform: gpio