diff --git a/homeassistant/components/zha/core/const.py b/homeassistant/components/zha/core/const.py index de373215e52..acac96f3162 100644 --- a/homeassistant/components/zha/core/const.py +++ b/homeassistant/components/zha/core/const.py @@ -128,6 +128,7 @@ CONF_CUSTOM_QUIRKS_PATH = "custom_quirks_path" CONF_DATABASE = "database_path" CONF_DEFAULT_LIGHT_TRANSITION = "default_light_transition" CONF_DEVICE_CONFIG = "device_config" +CONF_ENABLE_ENHANCED_LIGHT_TRANSITION = "enhanced_light_transition" CONF_ENABLE_IDENTIFY_ON_JOIN = "enable_identify_on_join" CONF_ENABLE_QUIRKS = "enable_quirks" CONF_FLOWCONTROL = "flow_control" @@ -143,6 +144,7 @@ CONF_DEFAULT_CONSIDER_UNAVAILABLE_BATTERY = 60 * 60 * 6 # 6 hours CONF_ZHA_OPTIONS_SCHEMA = vol.Schema( { vol.Optional(CONF_DEFAULT_LIGHT_TRANSITION): cv.positive_int, + vol.Required(CONF_ENABLE_ENHANCED_LIGHT_TRANSITION, default=False): cv.boolean, vol.Required(CONF_ENABLE_IDENTIFY_ON_JOIN, default=True): cv.boolean, vol.Optional( CONF_CONSIDER_UNAVAILABLE_MAINS, diff --git a/homeassistant/components/zha/light.py b/homeassistant/components/zha/light.py index 8aab3d20a5c..6c26e17188b 100644 --- a/homeassistant/components/zha/light.py +++ b/homeassistant/components/zha/light.py @@ -41,6 +41,7 @@ from .core.const import ( CHANNEL_LEVEL, CHANNEL_ON_OFF, CONF_DEFAULT_LIGHT_TRANSITION, + CONF_ENABLE_ENHANCED_LIGHT_TRANSITION, DATA_ZHA, EFFECT_BLINK, EFFECT_BREATHE, @@ -117,6 +118,7 @@ class BaseLight(LogMixin, light.LightEntity): self._off_with_transition: bool = False self._off_brightness: int | None = None self._zha_config_transition = self._DEFAULT_MIN_TRANSITION_TIME + self._zha_config_enhanced_light_transition: bool = False self._on_off_channel = None self._level_channel = None self._color_channel = None @@ -174,7 +176,7 @@ class BaseLight(LogMixin, light.LightEntity): # move to level, on, color, move to level... We also will not set this if the bulb is already in the # desired color mode with the desired color or color temperature. new_color_provided_while_off = ( - not isinstance(self, LightGroup) + self._zha_config_enhanced_light_transition and not self._FORCE_ON and not self._attr_state and ( @@ -482,6 +484,12 @@ class Light(BaseLight, ZhaEntity): CONF_DEFAULT_LIGHT_TRANSITION, 0, ) + self._zha_config_enhanced_light_transition = async_get_zha_config_value( + zha_device.gateway.config_entry, + ZHA_OPTIONS, + CONF_ENABLE_ENHANCED_LIGHT_TRANSITION, + False, + ) @callback def async_set_state(self, attr_id, attr_name, value): @@ -691,6 +699,7 @@ class LightGroup(BaseLight, ZhaGroupEntity): CONF_DEFAULT_LIGHT_TRANSITION, 0, ) + self._zha_config_enhanced_light_transition = False self._attr_color_mode = None # remove this when all ZHA platforms and base entities are updated diff --git a/homeassistant/components/zha/strings.json b/homeassistant/components/zha/strings.json index 5953df52e92..eb7753276f8 100644 --- a/homeassistant/components/zha/strings.json +++ b/homeassistant/components/zha/strings.json @@ -37,6 +37,7 @@ "config_panel": { "zha_options": { "title": "Global Options", + "enhanced_light_transition": "Enable enhanced light color/temperature transition from an off-state", "enable_identify_on_join": "Enable identify effect when devices join the network", "default_light_transition": "Default light transition time (seconds)", "consider_unavailable_mains": "Consider mains powered devices unavailable after (seconds)", diff --git a/homeassistant/components/zha/translations/en.json b/homeassistant/components/zha/translations/en.json index 00c78101a53..91c23acc044 100644 --- a/homeassistant/components/zha/translations/en.json +++ b/homeassistant/components/zha/translations/en.json @@ -50,6 +50,7 @@ "consider_unavailable_mains": "Consider mains powered devices unavailable after (seconds)", "default_light_transition": "Default light transition time (seconds)", "enable_identify_on_join": "Enable identify effect when devices join the network", + "enhanced_light_transition": "Enable enhanced light color/temperature transition from an off-state", "title": "Global Options" } }, diff --git a/tests/components/zha/conftest.py b/tests/components/zha/conftest.py index d9223027668..b1041a3e2a3 100644 --- a/tests/components/zha/conftest.py +++ b/tests/components/zha/conftest.py @@ -70,11 +70,14 @@ async def config_entry_fixture(hass): }, options={ zha_const.CUSTOM_CONFIGURATION: { + zha_const.ZHA_OPTIONS: { + zha_const.CONF_ENABLE_ENHANCED_LIGHT_TRANSITION: True, + }, zha_const.ZHA_ALARM_OPTIONS: { zha_const.CONF_ALARM_ARM_REQUIRES_CODE: False, zha_const.CONF_ALARM_MASTER_CODE: "4321", zha_const.CONF_ALARM_FAILED_TRIES: 2, - } + }, } }, ) diff --git a/tests/components/zha/test_light.py b/tests/components/zha/test_light.py index f892448dc69..c5b02f1a02f 100644 --- a/tests/components/zha/test_light.py +++ b/tests/components/zha/test_light.py @@ -560,7 +560,7 @@ async def test_transitions( dev1_cluster_level.request.reset_mock() - # test non 0 length transition and color temp while turning light on (color_provided_while_off) + # test non 0 length transition and color temp while turning light on (new_color_provided_while_off) await hass.services.async_call( LIGHT_DOMAIN, "turn_on", @@ -596,7 +596,7 @@ async def test_transitions( 10, dev1_cluster_color.commands_by_name["move_to_color_temp"].schema, 235, # color temp mireds - 0, # transition time (ZCL time in 10ths of a second) - no transition when color_provided_while_off + 0, # transition time (ZCL time in 10ths of a second) - no transition when new_color_provided_while_off expect_reply=True, manufacturer=None, tries=1, @@ -645,7 +645,7 @@ async def test_transitions( dev1_cluster_color.request.reset_mock() dev1_cluster_level.request.reset_mock() - # test no transition provided and color temp while turning light on (color_provided_while_off) + # test no transition provided and color temp while turning light on (new_color_provided_while_off) await hass.services.async_call( LIGHT_DOMAIN, "turn_on", @@ -680,7 +680,7 @@ async def test_transitions( 10, dev1_cluster_color.commands_by_name["move_to_color_temp"].schema, 236, # color temp mireds - 0, # transition time (ZCL time in 10ths of a second) - no transition when color_provided_while_off + 0, # transition time (ZCL time in 10ths of a second) - no transition when new_color_provided_while_off expect_reply=True, manufacturer=None, tries=1, @@ -761,7 +761,7 @@ async def test_transitions( 10, dev1_cluster_color.commands_by_name["move_to_color_temp"].schema, 236, # color temp mireds - 0, # transition time (ZCL time in 10ths of a second) - no transition when color_provided_while_off + 0, # transition time (ZCL time in 10ths of a second) - no transition when new_color_provided_while_off expect_reply=True, manufacturer=None, tries=1, @@ -854,7 +854,7 @@ async def test_transitions( dev2_cluster_on_off.request.reset_mock() - # test non 0 length transition and color temp while turning light on and sengled (color_provided_while_off) + # test non 0 length transition and color temp while turning light on and sengled (new_color_provided_while_off) await hass.services.async_call( LIGHT_DOMAIN, "turn_on", @@ -890,7 +890,7 @@ async def test_transitions( 10, dev2_cluster_color.commands_by_name["move_to_color_temp"].schema, 235, # color temp mireds - 1, # transition time (ZCL time in 10ths of a second) - sengled transition == 1 when color_provided_while_off + 1, # transition time (ZCL time in 10ths of a second) - sengled transition == 1 when new_color_provided_while_off expect_reply=True, manufacturer=None, tries=1, @@ -937,7 +937,7 @@ async def test_transitions( dev2_cluster_on_off.request.reset_mock() - # test non 0 length transition and color temp while turning group light on (color_provided_while_off) + # test non 0 length transition and color temp while turning group light on (new_color_provided_while_off) await hass.services.async_call( LIGHT_DOMAIN, "turn_on", @@ -960,13 +960,13 @@ async def test_transitions( assert group_level_channel.request.call_count == 1 assert group_level_channel.request.await_count == 1 - # groups are omitted from the 3 call dance for color_provided_while_off + # groups are omitted from the 3 call dance for new_color_provided_while_off assert group_color_channel.request.call_args == call( False, 10, dev2_cluster_color.commands_by_name["move_to_color_temp"].schema, 235, # color temp mireds - 10.0, # transition time (ZCL time in 10ths of a second) - sengled transition == 1 when color_provided_while_off + 10.0, # transition time (ZCL time in 10ths of a second) - sengled transition == 1 when new_color_provided_while_off expect_reply=True, manufacturer=None, tries=1, @@ -1074,7 +1074,7 @@ async def test_transitions( dev2_cluster_level.request.reset_mock() - # test eWeLink color temp while turning light on from off (color_provided_while_off) + # test eWeLink color temp while turning light on from off (new_color_provided_while_off) await hass.services.async_call( LIGHT_DOMAIN, "turn_on",