From fcc14933d0526c3da5cb59053224368ebefcd4f1 Mon Sep 17 00:00:00 2001 From: Keith Lamprecht <1894492+Nixon506E@users.noreply.github.com> Date: Wed, 3 Feb 2021 09:42:52 -0500 Subject: [PATCH] Add transitiontime to hue scene service (#45785) --- homeassistant/components/hue/bridge.py | 15 +++++++++-- homeassistant/components/hue/const.py | 2 ++ tests/components/hue/test_bridge.py | 35 ++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/hue/bridge.py b/homeassistant/components/hue/bridge.py index 880d9abcc35..201e9f3a546 100644 --- a/homeassistant/components/hue/bridge.py +++ b/homeassistant/components/hue/bridge.py @@ -19,6 +19,7 @@ from .const import ( CONF_ALLOW_UNREACHABLE, DEFAULT_ALLOW_HUE_GROUPS, DEFAULT_ALLOW_UNREACHABLE, + DEFAULT_SCENE_TRANSITION, LOGGER, ) from .errors import AuthenticationRequired, CannotConnect @@ -28,8 +29,15 @@ from .sensor_base import SensorManager SERVICE_HUE_SCENE = "hue_activate_scene" ATTR_GROUP_NAME = "group_name" ATTR_SCENE_NAME = "scene_name" +ATTR_TRANSITION = "transition" SCENE_SCHEMA = vol.Schema( - {vol.Required(ATTR_GROUP_NAME): cv.string, vol.Required(ATTR_SCENE_NAME): cv.string} + { + vol.Required(ATTR_GROUP_NAME): cv.string, + vol.Required(ATTR_SCENE_NAME): cv.string, + vol.Optional( + ATTR_TRANSITION, default=DEFAULT_SCENE_TRANSITION + ): cv.positive_int, + } ) # How long should we sleep if the hub is busy HUB_BUSY_SLEEP = 0.5 @@ -201,6 +209,7 @@ class HueBridge: """Service to call directly into bridge to set scenes.""" group_name = call.data[ATTR_GROUP_NAME] scene_name = call.data[ATTR_SCENE_NAME] + transition = call.data.get(ATTR_TRANSITION, DEFAULT_SCENE_TRANSITION) group = next( (group for group in self.api.groups.values() if group.name == group_name), @@ -236,7 +245,9 @@ class HueBridge: LOGGER.warning("Unable to find scene %s", scene_name) return False - return await self.async_request_call(partial(group.set_action, scene=scene.id)) + return await self.async_request_call( + partial(group.set_action, scene=scene.id, transitiontime=transition) + ) async def handle_unauthorized_error(self): """Create a new config flow when the authorization is no longer valid.""" diff --git a/homeassistant/components/hue/const.py b/homeassistant/components/hue/const.py index e2189515482..4fa11f2ad58 100644 --- a/homeassistant/components/hue/const.py +++ b/homeassistant/components/hue/const.py @@ -13,3 +13,5 @@ DEFAULT_ALLOW_UNREACHABLE = False CONF_ALLOW_HUE_GROUPS = "allow_hue_groups" DEFAULT_ALLOW_HUE_GROUPS = True + +DEFAULT_SCENE_TRANSITION = 4 diff --git a/tests/components/hue/test_bridge.py b/tests/components/hue/test_bridge.py index 3e6465d6bc8..29bc2acf03a 100644 --- a/tests/components/hue/test_bridge.py +++ b/tests/components/hue/test_bridge.py @@ -192,6 +192,41 @@ async def test_hue_activate_scene(hass, mock_api): assert mock_api.mock_requests[2]["path"] == "groups/group_1/action" +async def test_hue_activate_scene_transition(hass, mock_api): + """Test successful hue_activate_scene with transition.""" + config_entry = config_entries.ConfigEntry( + 1, + hue.DOMAIN, + "Mock Title", + {"host": "mock-host", "username": "mock-username"}, + "test", + config_entries.CONN_CLASS_LOCAL_POLL, + system_options={}, + options={CONF_ALLOW_HUE_GROUPS: True, CONF_ALLOW_UNREACHABLE: False}, + ) + hue_bridge = bridge.HueBridge(hass, config_entry) + + mock_api.mock_group_responses.append(GROUP_RESPONSE) + mock_api.mock_scene_responses.append(SCENE_RESPONSE) + + with patch("aiohue.Bridge", return_value=mock_api), patch.object( + hass.config_entries, "async_forward_entry_setup" + ): + assert await hue_bridge.async_setup() is True + + assert hue_bridge.api is mock_api + + call = Mock() + call.data = {"group_name": "Group 1", "scene_name": "Cozy dinner", "transition": 30} + with patch("aiohue.Bridge", return_value=mock_api): + assert await hue_bridge.hue_activate_scene(call) is None + + assert len(mock_api.mock_requests) == 3 + assert mock_api.mock_requests[2]["json"]["scene"] == "scene_1" + assert mock_api.mock_requests[2]["json"]["transitiontime"] == 30 + assert mock_api.mock_requests[2]["path"] == "groups/group_1/action" + + async def test_hue_activate_scene_group_not_found(hass, mock_api): """Test failed hue_activate_scene due to missing group.""" config_entry = config_entries.ConfigEntry(