From 64b1ccd8f6f6dda392b1865a418ff0d73c63b8c9 Mon Sep 17 00:00:00 2001 From: Alex Popoutsis <41379678+apop880@users.noreply.github.com> Date: Sun, 25 Oct 2020 06:44:26 -0500 Subject: [PATCH] Add WLED preset service (#42217) Co-authored-by: djtimca <60706061+djtimca@users.noreply.github.com> --- homeassistant/components/wled/const.py | 1 + homeassistant/components/wled/light.py | 21 ++++++++++ homeassistant/components/wled/services.yaml | 9 +++++ tests/components/wled/test_light.py | 44 +++++++++++++++++++++ 4 files changed, 75 insertions(+) diff --git a/homeassistant/components/wled/const.py b/homeassistant/components/wled/const.py index f50e17c01cc..e0880dd40fd 100644 --- a/homeassistant/components/wled/const.py +++ b/homeassistant/components/wled/const.py @@ -29,3 +29,4 @@ CURRENT_MA = "mA" # Services SERVICE_EFFECT = "effect" +SERVICE_PRESET = "preset" diff --git a/homeassistant/components/wled/light.py b/homeassistant/components/wled/light.py index 9c6d027b058..527d985a47b 100644 --- a/homeassistant/components/wled/light.py +++ b/homeassistant/components/wled/light.py @@ -42,6 +42,7 @@ from .const import ( ATTR_SPEED, DOMAIN, SERVICE_EFFECT, + SERVICE_PRESET, ) PARALLEL_UPDATES = 1 @@ -73,6 +74,16 @@ async def async_setup_entry( "async_effect", ) + platform.async_register_entity_service( + SERVICE_PRESET, + { + vol.Required(ATTR_PRESET): vol.All( + vol.Coerce(int), vol.Range(min=-1, max=65535) + ), + }, + "async_preset", + ) + update_segments = partial( async_update_segments, entry, coordinator, {}, async_add_entities ) @@ -372,6 +383,16 @@ class WLEDSegmentLight(LightEntity, WLEDDeviceEntity): await self.coordinator.wled.segment(**data) + @wled_exception_handler + async def async_preset( + self, + preset: int, + ) -> None: + """Set a WLED light to a saved preset.""" + data = {ATTR_PRESET: preset} + + await self.coordinator.wled.preset(**data) + @callback def async_update_segments( diff --git a/homeassistant/components/wled/services.yaml b/homeassistant/components/wled/services.yaml index 7b9a8d01ba1..723e593e676 100644 --- a/homeassistant/components/wled/services.yaml +++ b/homeassistant/components/wled/services.yaml @@ -19,3 +19,12 @@ effect: reverse: description: Reverse the effect. Either true to reverse or false otherwise. example: false +preset: + description: Calls a preset on the WLED device + fields: + entity_id: + description: Name of the WLED light entity. + example: "light.wled" + preset: + description: ID of the WLED preset + example: 6 diff --git a/tests/components/wled/test_light.py b/tests/components/wled/test_light.py index e2db58b1246..fbcc6ca71b6 100644 --- a/tests/components/wled/test_light.py +++ b/tests/components/wled/test_light.py @@ -23,6 +23,7 @@ from homeassistant.components.wled.const import ( ATTR_SPEED, DOMAIN, SERVICE_EFFECT, + SERVICE_PRESET, ) from homeassistant.const import ( ATTR_ENTITY_ID, @@ -587,3 +588,46 @@ async def test_effect_service_error( state = hass.states.get("light.wled_rgb_light_segment_0") assert state.state == STATE_ON assert "Invalid response from API" in caplog.text + + +async def test_preset_service( + hass: HomeAssistant, aioclient_mock: AiohttpClientMocker +) -> None: + """Test the preset service of a WLED light.""" + await init_integration(hass, aioclient_mock) + + with patch("wled.WLED.preset") as light_mock: + await hass.services.async_call( + DOMAIN, + SERVICE_PRESET, + { + ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0", + ATTR_PRESET: 1, + }, + blocking=True, + ) + await hass.async_block_till_done() + light_mock.assert_called_once_with( + preset=1, + ) + + +async def test_preset_service_error( + hass: HomeAssistant, aioclient_mock: AiohttpClientMocker, caplog +) -> None: + """Test error handling of the WLED preset service.""" + aioclient_mock.post("http://192.168.1.123:80/json/state", text="", status=400) + await init_integration(hass, aioclient_mock) + + with patch("homeassistant.components.wled.WLED.update"): + await hass.services.async_call( + DOMAIN, + SERVICE_PRESET, + {ATTR_ENTITY_ID: "light.wled_rgb_light_segment_0", ATTR_PRESET: 1}, + blocking=True, + ) + await hass.async_block_till_done() + + state = hass.states.get("light.wled_rgb_light_segment_0") + assert state.state == STATE_ON + assert "Invalid response from API" in caplog.text