From 0871bf13a4b7cb2cf028b96219b1f49f4cf7abdc Mon Sep 17 00:00:00 2001 From: Marcel van der Veldt Date: Wed, 2 Apr 2025 15:39:31 +0200 Subject: [PATCH] Deprecate None effect instead of breaking it for Hue (#142073) * Deprecate effect none instead of breaking it for Hue * add guard for unknown effect value * revert guard * Fix * Add test * Add test * Add test --------- Co-authored-by: Joostlek --- homeassistant/components/hue/strings.json | 6 ++++ homeassistant/components/hue/v2/light.py | 21 +++++++++++ tests/components/hue/test_light_v2.py | 44 +++++++++++++++++++++-- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/hue/strings.json b/homeassistant/components/hue/strings.json index 6d2e9054c6f..3326dd1043f 100644 --- a/homeassistant/components/hue/strings.json +++ b/homeassistant/components/hue/strings.json @@ -197,5 +197,11 @@ } } } + }, + "issues": { + "deprecated_effect_none": { + "title": "Light turned on with deprecated effect", + "description": "A light was turned on with the deprecated effect `None`. This has been replaced with `off`. Please update any automations, scenes, or scripts that use this effect." + } } } diff --git a/homeassistant/components/hue/v2/light.py b/homeassistant/components/hue/v2/light.py index 757b69c7b7b..8eb7ec8936e 100644 --- a/homeassistant/components/hue/v2/light.py +++ b/homeassistant/components/hue/v2/light.py @@ -29,6 +29,7 @@ from homeassistant.components.light import ( from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback +from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue from homeassistant.util import color as color_util from ..bridge import HueBridge @@ -44,6 +45,9 @@ FALLBACK_MIN_KELVIN = 6500 FALLBACK_MAX_KELVIN = 2000 FALLBACK_KELVIN = 5800 # halfway +# HA 2025.4 replaced the deprecated effect "None" with HA default "off" +DEPRECATED_EFFECT_NONE = "None" + async def async_setup_entry( hass: HomeAssistant, @@ -233,6 +237,23 @@ class HueLight(HueBaseEntity, LightEntity): self._color_temp_active = color_temp is not None flash = kwargs.get(ATTR_FLASH) effect = effect_str = kwargs.get(ATTR_EFFECT) + if effect_str == DEPRECATED_EFFECT_NONE: + # deprecated effect "None" is now "off" + effect_str = EFFECT_OFF + async_create_issue( + self.hass, + DOMAIN, + "deprecated_effect_none", + breaks_in_ha_version="2025.10.0", + is_fixable=False, + severity=IssueSeverity.WARNING, + translation_key="deprecated_effect_none", + ) + self.logger.warning( + "Detected deprecated effect 'None' in %s, use 'off' instead. " + "This will stop working in HA 2025.10", + self.entity_id, + ) if effect_str == EFFECT_OFF: # ignore effect if set to "off" and we have no effect active # the special effect "off" is only used to stop an active effect diff --git a/tests/components/hue/test_light_v2.py b/tests/components/hue/test_light_v2.py index 3d323d4d31c..f4a6fcfba93 100644 --- a/tests/components/hue/test_light_v2.py +++ b/tests/components/hue/test_light_v2.py @@ -2,9 +2,14 @@ from unittest.mock import Mock -from homeassistant.components.light import ColorMode +from homeassistant.components.light import ( + ATTR_EFFECT, + DOMAIN as LIGHT_DOMAIN, + ColorMode, +) +from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_ON from homeassistant.core import HomeAssistant -from homeassistant.helpers import entity_registry as er +from homeassistant.helpers import entity_registry as er, issue_registry as ir from homeassistant.util.json import JsonArrayType from .conftest import setup_platform @@ -639,3 +644,38 @@ async def test_grouped_lights( mock_bridge_v2.mock_requests[index]["json"]["identify"]["action"] == "identify" ) + + +async def test_light_turn_on_service_deprecation( + hass: HomeAssistant, + mock_bridge_v2: Mock, + v2_resources_test_data: JsonArrayType, + issue_registry: ir.IssueRegistry, +) -> None: + """Test calling the turn on service on a light.""" + await mock_bridge_v2.api.load_test_data(v2_resources_test_data) + + test_light_id = "light.hue_light_with_color_temperature_only" + + await setup_platform(hass, mock_bridge_v2, "light") + + event = { + "id": "3a6710fa-4474-4eba-b533-5e6e72968feb", + "type": "light", + "effects": {"status": "candle"}, + } + mock_bridge_v2.api.emit_event("update", event) + await hass.async_block_till_done() + + # test disable effect + # it should send a request with effect set to "no_effect" + await hass.services.async_call( + LIGHT_DOMAIN, + SERVICE_TURN_ON, + { + ATTR_ENTITY_ID: test_light_id, + ATTR_EFFECT: "None", + }, + blocking=True, + ) + assert mock_bridge_v2.mock_requests[0]["json"]["effects"]["effect"] == "no_effect"