1
mirror of https://github.com/home-assistant/core synced 2024-09-09 12:51:22 +02:00

Round Hue transition to steps of 100ms (#62619)

* Adding round() to transition before firing turn_on, turn_off #62608
This commit is contained in:
Christian Manivong 2021-12-23 15:08:24 +01:00 committed by GitHub
parent 1bbeaa722c
commit 772428e70f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 45 additions and 39 deletions

View File

@ -8,6 +8,7 @@ from aiohue.v2.controllers.events import EventType
from aiohue.v2.controllers.scenes import ScenesController
from aiohue.v2.models.scene import Scene as HueScene
from homeassistant.components.light import ATTR_TRANSITION
from homeassistant.components.scene import Scene as SceneEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
@ -16,6 +17,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .bridge import HueBridge
from .const import DOMAIN
from .v2.entity import HueBaseEntity
from .v2.helpers import normalize_hue_transition
async def async_setup_entry(
@ -94,11 +96,9 @@ class HueSceneEntity(HueBaseEntity, SceneEntity):
async def async_activate(self, **kwargs: Any) -> None:
"""Activate Hue scene."""
transition = kwargs.get("transition")
if transition is not None:
# hue transition duration is in milliseconds
transition = int(transition * 1000)
transition = normalize_hue_transition(kwargs.get(ATTR_TRANSITION))
dynamic = kwargs.get("dynamic", self.is_dynamic)
await self.bridge.async_request_call(
self.controller.recall,
self.resource.id,

View File

@ -29,6 +29,7 @@ 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
ALLOWED_ERRORS = [
"device (groupedLight) has communication issues, command (on) may not have effect",
@ -147,17 +148,11 @@ class GroupedHueLight(HueBaseEntity, LightEntity):
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the light on."""
transition = kwargs.get(ATTR_TRANSITION)
transition = normalize_hue_transition(kwargs.get(ATTR_TRANSITION))
xy_color = kwargs.get(ATTR_XY_COLOR)
color_temp = kwargs.get(ATTR_COLOR_TEMP)
brightness = kwargs.get(ATTR_BRIGHTNESS)
brightness = normalize_hue_brightness(kwargs.get(ATTR_BRIGHTNESS))
flash = kwargs.get(ATTR_FLASH)
if brightness is not None:
# Hue uses a range of [0, 100] to control brightness.
brightness = float((brightness / 255) * 100)
if transition is not None:
# hue transition duration is in milliseconds
transition = int(transition * 1000)
# NOTE: a grouped_light can only handle turn on/off
# To set other features, you'll have to control the attached lights
@ -193,10 +188,7 @@ class GroupedHueLight(HueBaseEntity, LightEntity):
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the light off."""
transition = kwargs.get(ATTR_TRANSITION)
if transition is not None:
# hue transition duration is in milliseconds
transition = int(transition * 1000)
transition = normalize_hue_transition(kwargs.get(ATTR_TRANSITION))
# NOTE: a grouped_light can only handle turn on/off
# To set other features, you'll have to control the attached lights

View File

@ -0,0 +1,21 @@
"""Helper functions for Philips Hue v2."""
def normalize_hue_brightness(brightness):
"""Returns calculated brightness values"""
if brightness is not None:
# Hue uses a range of [0, 100] to control brightness.
brightness = float((brightness / 255) * 100)
return brightness
def normalize_hue_transition(transition):
"""Returns 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

View File

@ -30,6 +30,7 @@ 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
ALLOWED_ERRORS = [
"device (light) has communication issues, command (on) may not have effect",
@ -155,17 +156,11 @@ class HueLight(HueBaseEntity, LightEntity):
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the device on."""
transition = kwargs.get(ATTR_TRANSITION)
transition = normalize_hue_transition(kwargs.get(ATTR_TRANSITION))
xy_color = kwargs.get(ATTR_XY_COLOR)
color_temp = kwargs.get(ATTR_COLOR_TEMP)
brightness = kwargs.get(ATTR_BRIGHTNESS)
brightness = normalize_hue_brightness(kwargs.get(ATTR_BRIGHTNESS))
flash = kwargs.get(ATTR_FLASH)
if brightness is not None:
# Hue uses a range of [0, 100] to control brightness.
brightness = float((brightness / 255) * 100)
if transition is not None:
# hue transition duration is in milliseconds
transition = int(transition * 1000)
await self.bridge.async_request_call(
self.controller.set_state,
@ -181,11 +176,9 @@ class HueLight(HueBaseEntity, LightEntity):
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the light off."""
transition = kwargs.get(ATTR_TRANSITION)
transition = normalize_hue_transition(kwargs.get(ATTR_TRANSITION))
flash = kwargs.get(ATTR_FLASH)
if transition is not None:
# hue transition duration is in milliseconds
transition = int(transition * 1000)
await self.bridge.async_request_call(
self.controller.set_state,
id=self.resource.id,

View File

@ -110,16 +110,16 @@ async def test_light_turn_on_service(hass, mock_bridge_v2, v2_resources_test_dat
assert test_light.attributes["color_mode"] == COLOR_MODE_COLOR_TEMP
assert test_light.attributes["brightness"] == 255
# test again with sending transition
# test again with sending transition with 250ms which should round up to 200ms
await hass.services.async_call(
"light",
"turn_on",
{"entity_id": test_light_id, "brightness_pct": 50, "transition": 6},
{"entity_id": test_light_id, "brightness_pct": 50, "transition": 0.25},
blocking=True,
)
assert len(mock_bridge_v2.mock_requests) == 2
assert mock_bridge_v2.mock_requests[1]["json"]["on"]["on"] is True
assert mock_bridge_v2.mock_requests[1]["json"]["dynamics"]["duration"] == 6000
assert mock_bridge_v2.mock_requests[1]["json"]["dynamics"]["duration"] == 200
# test again with sending flash/alert
await hass.services.async_call(
@ -170,12 +170,12 @@ async def test_light_turn_off_service(hass, mock_bridge_v2, v2_resources_test_da
await hass.services.async_call(
"light",
"turn_off",
{"entity_id": test_light_id, "transition": 6},
{"entity_id": test_light_id, "transition": 0.25},
blocking=True,
)
assert len(mock_bridge_v2.mock_requests) == 2
assert mock_bridge_v2.mock_requests[1]["json"]["on"]["on"] is False
assert mock_bridge_v2.mock_requests[1]["json"]["dynamics"]["duration"] == 6000
assert mock_bridge_v2.mock_requests[1]["json"]["dynamics"]["duration"] == 200
async def test_light_added(hass, mock_bridge_v2):
@ -310,7 +310,7 @@ async def test_grouped_lights(hass, mock_bridge_v2, v2_resources_test_data):
"entity_id": test_light_id,
"brightness_pct": 100,
"xy_color": (0.123, 0.123),
"transition": 6,
"transition": 0.25,
},
blocking=True,
)
@ -325,7 +325,7 @@ async def test_grouped_lights(hass, mock_bridge_v2, v2_resources_test_data):
assert mock_bridge_v2.mock_requests[index]["json"]["color"]["xy"]["x"] == 0.123
assert mock_bridge_v2.mock_requests[index]["json"]["color"]["xy"]["y"] == 0.123
assert (
mock_bridge_v2.mock_requests[index]["json"]["dynamics"]["duration"] == 6000
mock_bridge_v2.mock_requests[index]["json"]["dynamics"]["duration"] == 200
)
# Now generate update events by emitting the json we've sent as incoming events
@ -374,7 +374,7 @@ async def test_grouped_lights(hass, mock_bridge_v2, v2_resources_test_data):
"turn_off",
{
"entity_id": test_light_id,
"transition": 6,
"transition": 0.25,
},
blocking=True,
)
@ -384,5 +384,5 @@ async def test_grouped_lights(hass, mock_bridge_v2, v2_resources_test_data):
for index in range(0, 3):
assert mock_bridge_v2.mock_requests[index]["json"]["on"]["on"] is False
assert (
mock_bridge_v2.mock_requests[index]["json"]["dynamics"]["duration"] == 6000
mock_bridge_v2.mock_requests[index]["json"]["dynamics"]["duration"] == 200
)

View File

@ -77,13 +77,13 @@ async def test_scene_turn_on_service(hass, mock_bridge_v2, v2_resources_test_dat
await hass.services.async_call(
"scene",
"turn_on",
{"entity_id": test_entity_id, "transition": 6},
{"entity_id": test_entity_id, "transition": 0.25},
blocking=True,
)
assert len(mock_bridge_v2.mock_requests) == 2
assert mock_bridge_v2.mock_requests[1]["json"]["recall"] == {
"action": "active",
"duration": 6000,
"duration": 200,
}