Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds light switch platform #18562

Merged
merged 4 commits into from
Nov 20, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions homeassistant/components/light/switch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
"""
Light support for switch entities.

For more information about this platform, please refer to the documentation at
https://home-assistant.io/components/light.switch/
"""
import logging
import voluptuous as vol

from homeassistant.core import State, callback
from homeassistant.components.light import (
Light, PLATFORM_SCHEMA)
from homeassistant.components import switch
from homeassistant.const import (
STATE_ON,
ATTR_ENTITY_ID,
CONF_NAME,
CONF_ENTITY_ID,
STATE_UNAVAILABLE
)
from homeassistant.helpers.typing import HomeAssistantType, ConfigType
from homeassistant.helpers.event import async_track_state_change
import homeassistant.helpers.config_validation as cv

_LOGGER = logging.getLogger(__name__)

DEFAULT_NAME = 'Light Switch'

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Required(CONF_ENTITY_ID): cv.entity_domain(switch.DOMAIN)
})


async def async_setup_platform(hass: HomeAssistantType, config: ConfigType,
async_add_entities,
discovery_info=None) -> None:
"""Initialize Light Switch platform."""

async_add_entities([LightSwitch(config.get(CONF_NAME),
config[CONF_ENTITY_ID])])

class LightSwitch(Light):
frenck marked this conversation as resolved.
Show resolved Hide resolved
"""Represents a Switch as a Light."""

def __init__(self, name: str, switch_entity_id: str) -> None:
"""Initialize Light Switch."""
self._name = name # type: str
frenck marked this conversation as resolved.
Show resolved Hide resolved
self._switch_entity_id = switch_entity_id # type: str
frenck marked this conversation as resolved.
Show resolved Hide resolved
self._is_on = False # type: bool
frenck marked this conversation as resolved.
Show resolved Hide resolved
self._available = False # type: bool
frenck marked this conversation as resolved.
Show resolved Hide resolved
self._async_unsub_state_changed = None

@property
def name(self) -> str:
"""Return the name of the entity."""
return self._name

@property
def is_on(self) -> bool:
"""Return true if light switch is on."""
return self._is_on

@property
def available(self) -> bool:
"""Return true if light switch is on."""
return self._available

@property
def should_poll(self) -> bool:
"""No polling needed for a light switch."""
return False

async def async_turn_on(self, **kwargs):
"""Forward the turn_on command to the switch in this light switch"""
data = {ATTR_ENTITY_ID: self._switch_entity_id}
await self.hass.services.async_call(
switch.DOMAIN, switch.SERVICE_TURN_ON, data, blocking=True)

async def async_turn_off(self, **kwargs):
"""Forward the turn_off command to the switch in this light switch"""
data = {ATTR_ENTITY_ID: self._switch_entity_id}
await self.hass.services.async_call(
switch.DOMAIN, switch.SERVICE_TURN_OFF, data, blocking=True)

async def async_update(self):
"""Query the switch in this light switch and determine the state"""
switch_state = self.hass.states.get(self._switch_entity_id)

if switch_state is None:
self._available = False
return

self._is_on = switch_state.state == STATE_ON
self._available = switch_state.state != STATE_UNAVAILABLE

async def async_added_to_hass(self) -> None:
"""Register callbacks."""
@callback
def async_state_changed_listener(entity_id: str, old_state: State,
new_state: State):
"""Handle child updates."""
self.async_schedule_update_ha_state(True)

self._async_unsub_state_changed = async_track_state_change(
self.hass, self._switch_entity_id, async_state_changed_listener)
await self.async_update()
frenck marked this conversation as resolved.
Show resolved Hide resolved

async def async_will_remove_from_hass(self):
"""Handle removal from Home Assistant."""
if self._async_unsub_state_changed is not None:
self._async_unsub_state_changed()
self._async_unsub_state_changed = None
self._available = False
81 changes: 81 additions & 0 deletions tests/components/light/test_switch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
"""The tests for the Light Switch platform."""

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 default state."""
await async_setup_component(hass, 'light', {'light': {
'platform': 'switch', 'entity_id': 'switch.test',
'name': 'Christmas Tree Lights'
}})
await hass.async_block_till_done()

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

async def test_light_service_calls(hass):
frenck marked this conversation as resolved.
Show resolved Hide resolved
"""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.decorative_lights'}
]})
await hass.async_block_till_done()

assert hass.states.get('light.light_switch').state == 'on'

common.async_toggle(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'

common.async_turn_on(hass, 'light.light_switch')
await hass.async_block_till_done()

assert hass.states.get('switch.decorative_lights').state == 'on'
assert hass.states.get('light.light_switch').state == 'on'

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):
frenck marked this conversation as resolved.
Show resolved Hide resolved
"""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'

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'

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'