diff --git a/homeassistant/components/hue/v2/group.py b/homeassistant/components/hue/v2/group.py index 52c1bc6117a..7ef91f684fe 100644 --- a/homeassistant/components/hue/v2/group.py +++ b/homeassistant/components/hue/v2/group.py @@ -31,7 +31,11 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from ..bridge import HueBridge from ..const import CONF_ALLOW_HUE_GROUPS, DOMAIN from .entity import HueBaseEntity -from .helpers import normalize_hue_brightness, normalize_hue_transition +from .helpers import ( + normalize_hue_brightness, + normalize_hue_colortemp, + normalize_hue_transition, +) ALLOWED_ERRORS = [ "device (groupedLight) has communication issues, command (on) may not have effect", @@ -151,7 +155,7 @@ class GroupedHueLight(HueBaseEntity, LightEntity): """Turn the light on.""" transition = normalize_hue_transition(kwargs.get(ATTR_TRANSITION)) xy_color = kwargs.get(ATTR_XY_COLOR) - color_temp = kwargs.get(ATTR_COLOR_TEMP) + color_temp = normalize_hue_colortemp(kwargs.get(ATTR_COLOR_TEMP)) brightness = normalize_hue_brightness(kwargs.get(ATTR_BRIGHTNESS)) flash = kwargs.get(ATTR_FLASH) diff --git a/homeassistant/components/hue/v2/helpers.py b/homeassistant/components/hue/v2/helpers.py index 307e7c55e03..97fdbe6160a 100644 --- a/homeassistant/components/hue/v2/helpers.py +++ b/homeassistant/components/hue/v2/helpers.py @@ -1,7 +1,8 @@ """Helper functions for Philips Hue v2.""" +from __future__ import annotations -def normalize_hue_brightness(brightness): +def normalize_hue_brightness(brightness: float | None) -> float | None: """Return calculated brightness values.""" if brightness is not None: # Hue uses a range of [0, 100] to control brightness. @@ -10,10 +11,19 @@ def normalize_hue_brightness(brightness): return brightness -def normalize_hue_transition(transition): +def normalize_hue_transition(transition: float | None) -> float | None: """Return rounded transition values.""" if transition is not None: # hue transition duration is in milliseconds and round them to 100ms transition = int(round(transition, 1) * 1000) return transition + + +def normalize_hue_colortemp(colortemp: int | None) -> int | None: + """Return color temperature within Hue's ranges.""" + if colortemp is not None: + # Hue only accepts a range between 153..500 + colortemp = min(colortemp, 500) + colortemp = max(colortemp, 153) + return colortemp diff --git a/homeassistant/components/hue/v2/light.py b/homeassistant/components/hue/v2/light.py index 91afbe53e45..42444fd9ad0 100644 --- a/homeassistant/components/hue/v2/light.py +++ b/homeassistant/components/hue/v2/light.py @@ -30,7 +30,11 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback from ..bridge import HueBridge from ..const import DOMAIN from .entity import HueBaseEntity -from .helpers import normalize_hue_brightness, normalize_hue_transition +from .helpers import ( + normalize_hue_brightness, + normalize_hue_colortemp, + normalize_hue_transition, +) ALLOWED_ERRORS = [ "device (light) has communication issues, command (on) may not have effect", @@ -158,7 +162,7 @@ class HueLight(HueBaseEntity, LightEntity): """Turn the device on.""" transition = normalize_hue_transition(kwargs.get(ATTR_TRANSITION)) xy_color = kwargs.get(ATTR_XY_COLOR) - color_temp = kwargs.get(ATTR_COLOR_TEMP) + color_temp = normalize_hue_colortemp(kwargs.get(ATTR_COLOR_TEMP)) brightness = normalize_hue_brightness(kwargs.get(ATTR_BRIGHTNESS)) flash = kwargs.get(ATTR_FLASH) diff --git a/tests/components/hue/test_light_v2.py b/tests/components/hue/test_light_v2.py index 970497214c5..c7578df3a49 100644 --- a/tests/components/hue/test_light_v2.py +++ b/tests/components/hue/test_light_v2.py @@ -141,6 +141,25 @@ async def test_light_turn_on_service(hass, mock_bridge_v2, v2_resources_test_dat assert len(mock_bridge_v2.mock_requests) == 4 assert mock_bridge_v2.mock_requests[3]["json"]["identify"]["action"] == "identify" + # test again with sending a colortemperature which is out of range + # which should be normalized to the upper/lower bounds Hue can handle + await hass.services.async_call( + "light", + "turn_on", + {"entity_id": test_light_id, "color_temp": 50}, + blocking=True, + ) + assert len(mock_bridge_v2.mock_requests) == 5 + assert mock_bridge_v2.mock_requests[4]["json"]["color_temperature"]["mirek"] == 153 + await hass.services.async_call( + "light", + "turn_on", + {"entity_id": test_light_id, "color_temp": 550}, + blocking=True, + ) + assert len(mock_bridge_v2.mock_requests) == 6 + assert mock_bridge_v2.mock_requests[5]["json"]["color_temperature"]["mirek"] == 500 + async def test_light_turn_off_service(hass, mock_bridge_v2, v2_resources_test_data): """Test calling the turn off service on a light."""