From cc156c767d5e2a981e493f9d58d4c90b60506d08 Mon Sep 17 00:00:00 2001 From: Erik Montnemery Date: Mon, 28 Mar 2022 12:28:15 +0200 Subject: [PATCH] Revert light.switch to 2022.3 (#68772) --- homeassistant/components/switch/light.py | 79 +++++++++++++++++++++-- tests/components/switch/test_light.py | 82 ++++++++++++++++++++---- 2 files changed, 146 insertions(+), 15 deletions(-) diff --git a/homeassistant/components/switch/light.py b/homeassistant/components/switch/light.py index ad75d229d51..ac548652953 100644 --- a/homeassistant/components/switch/light.py +++ b/homeassistant/components/switch/light.py @@ -1,15 +1,29 @@ """Light support for switch entities.""" from __future__ import annotations +from typing import Any + import voluptuous as vol -from homeassistant.components.light import PLATFORM_SCHEMA -from homeassistant.components.switch_as_x import LightSwitch -from homeassistant.const import CONF_ENTITY_ID, CONF_NAME -from homeassistant.core import HomeAssistant +from homeassistant.components.light import ( + COLOR_MODE_ONOFF, + PLATFORM_SCHEMA, + LightEntity, +) +from homeassistant.const import ( + ATTR_ENTITY_ID, + CONF_ENTITY_ID, + CONF_NAME, + SERVICE_TURN_OFF, + SERVICE_TURN_ON, + STATE_ON, + STATE_UNAVAILABLE, +) +from homeassistant.core import Event, HomeAssistant, callback from homeassistant.helpers import entity_registry as er import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.event import async_track_state_change_event from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType from .const import DOMAIN as SWITCH_DOMAIN @@ -44,3 +58,60 @@ async def async_setup_platform( ) ] ) + + +class LightSwitch(LightEntity): + """Represents a Switch as a Light.""" + + _attr_color_mode = COLOR_MODE_ONOFF + _attr_should_poll = False + _attr_supported_color_modes = {COLOR_MODE_ONOFF} + + def __init__(self, name: str, switch_entity_id: str, unique_id: str | None) -> None: + """Initialize Light Switch.""" + self._attr_name = name + self._attr_unique_id = unique_id + self._switch_entity_id = switch_entity_id + + async def async_turn_on(self, **kwargs: Any) -> None: + """Forward the turn_on command to the switch in this light switch.""" + await self.hass.services.async_call( + SWITCH_DOMAIN, + SERVICE_TURN_ON, + {ATTR_ENTITY_ID: self._switch_entity_id}, + blocking=True, + context=self._context, + ) + + async def async_turn_off(self, **kwargs: Any) -> None: + """Forward the turn_off command to the switch in this light switch.""" + await self.hass.services.async_call( + SWITCH_DOMAIN, + SERVICE_TURN_OFF, + {ATTR_ENTITY_ID: self._switch_entity_id}, + blocking=True, + context=self._context, + ) + + async def async_added_to_hass(self) -> None: + """Register callbacks.""" + + @callback + def async_state_changed_listener(event: Event | None = None) -> None: + """Handle child updates.""" + if ( + state := self.hass.states.get(self._switch_entity_id) + ) is None or state.state == STATE_UNAVAILABLE: + self._attr_available = False + return + self._attr_available = True + self._attr_is_on = state.state == STATE_ON + self.async_write_ha_state() + + self.async_on_remove( + async_track_state_change_event( + self.hass, [self._switch_entity_id], async_state_changed_listener + ) + ) + # Call once on adding + async_state_changed_listener() diff --git a/tests/components/switch/test_light.py b/tests/components/switch/test_light.py index e75e0e6d313..62fef242e9f 100644 --- a/tests/components/switch/test_light.py +++ b/tests/components/switch/test_light.py @@ -1,10 +1,18 @@ """The tests for the Light Switch platform.""" +from homeassistant.components.light import ( + ATTR_COLOR_MODE, + ATTR_SUPPORTED_COLOR_MODES, + COLOR_MODE_ONOFF, +) from homeassistant.setup import async_setup_component +from tests.components.light import common +from tests.components.switch import common as switch_common + async def test_default_state(hass): - """Test light switch yaml config.""" + """Test light switch default state.""" await async_setup_component( hass, "light", @@ -18,21 +26,73 @@ async def test_default_state(hass): ) await hass.async_block_till_done() - assert hass.states.get("light.christmas_tree_lights") + state = hass.states.get("light.christmas_tree_lights") + assert state is not None + assert state.state == "unavailable" + assert state.attributes["supported_features"] == 0 + assert state.attributes.get("brightness") is None + assert state.attributes.get("hs_color") is None + assert state.attributes.get("color_temp") is None + assert state.attributes.get("white_value") is None + assert state.attributes.get("effect_list") is None + assert state.attributes.get("effect") is None + assert state.attributes.get(ATTR_SUPPORTED_COLOR_MODES) == [COLOR_MODE_ONOFF] + assert state.attributes.get(ATTR_COLOR_MODE) is None -async def test_default_state_no_name(hass): - """Test light switch default name.""" +async def test_light_service_calls(hass): + """Test service calls to light.""" + await async_setup_component(hass, "switch", {"switch": [{"platform": "demo"}]}) await async_setup_component( hass, "light", - { - "light": { - "platform": "switch", - "entity_id": "switch.test", - } - }, + {"light": [{"platform": "switch", "entity_id": "switch.decorative_lights"}]}, ) await hass.async_block_till_done() - assert hass.states.get("light.light_switch") + assert hass.states.get("light.light_switch").state == "on" + + await common.async_toggle(hass, "light.light_switch") + + assert hass.states.get("switch.decorative_lights").state == "off" + assert hass.states.get("light.light_switch").state == "off" + + await common.async_turn_on(hass, "light.light_switch") + + assert hass.states.get("switch.decorative_lights").state == "on" + assert hass.states.get("light.light_switch").state == "on" + assert ( + hass.states.get("light.light_switch").attributes.get(ATTR_COLOR_MODE) + == COLOR_MODE_ONOFF + ) + + await common.async_turn_off(hass, "light.light_switch") + await hass.async_block_till_done() + + assert hass.states.get("switch.decorative_lights").state == "off" + assert hass.states.get("light.light_switch").state == "off" + + +async def test_switch_service_calls(hass): + """Test service calls to switch.""" + await async_setup_component(hass, "switch", {"switch": [{"platform": "demo"}]}) + await async_setup_component( + hass, + "light", + {"light": [{"platform": "switch", "entity_id": "switch.decorative_lights"}]}, + ) + await hass.async_block_till_done() + + assert hass.states.get("light.light_switch").state == "on" + + await switch_common.async_turn_off(hass, "switch.decorative_lights") + await hass.async_block_till_done() + + assert hass.states.get("switch.decorative_lights").state == "off" + assert hass.states.get("light.light_switch").state == "off" + + await switch_common.async_turn_on(hass, "switch.decorative_lights") + await hass.async_block_till_done() + + assert hass.states.get("switch.decorative_lights").state == "on" + assert hass.states.get("light.light_switch").state == "on"