A Few changes

This commit is contained in:
Otto Winter
2018-02-20 00:03:44 +01:00
parent 73c80b9cad
commit 21bf83e63a

View File

@@ -2,19 +2,21 @@
This component allows several lights to be grouped into one light. This component allows several lights to be grouped into one light.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/light.grouped_light/ https://home-assistant.io/components/light.group/
""" """
import asyncio import asyncio
import logging import logging
import itertools import itertools
from typing import List, Tuple, Optional, TypeVar, Iterator from typing import List, Tuple, Optional, Iterator, Any
import voluptuous as vol import voluptuous as vol
from homeassistant.core import State from homeassistant.core import State, callback
from homeassistant.components import light from homeassistant.components import light
from homeassistant.const import ( from homeassistant.const import (STATE_OFF, STATE_ON, SERVICE_TURN_ON,
STATE_OFF, STATE_ON, SERVICE_TURN_ON, SERVICE_TURN_OFF, ATTR_ENTITY_ID, SERVICE_TURN_OFF, ATTR_ENTITY_ID, CONF_NAME,
CONF_NAME, CONF_ENTITIES, STATE_UNAVAILABLE, STATE_UNKNOWN) CONF_ENTITIES, STATE_UNAVAILABLE,
STATE_UNKNOWN, EVENT_HOMEASSISTANT_START)
from homeassistant.helpers.event import async_track_state_change from homeassistant.helpers.event import async_track_state_change
from homeassistant.helpers.typing import HomeAssistantType, ConfigType from homeassistant.helpers.typing import HomeAssistantType, ConfigType
from homeassistant.components.light import ( from homeassistant.components.light import (
@@ -25,13 +27,13 @@ import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DOMAIN = 'grouped_light' DOMAIN = 'group'
DEFAULT_NAME = 'Grouped Light' DEFAULT_NAME = 'Group Light'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_ENTITIES): cv.entity_ids,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Required(CONF_ENTITIES): cv.entity_ids,
}) })
SUPPORT_GROUP_LIGHT = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_EFFECT SUPPORT_GROUP_LIGHT = (SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_EFFECT
@@ -44,27 +46,21 @@ def async_setup_platform(hass: HomeAssistantType,
config: ConfigType, config: ConfigType,
async_add_devices, async_add_devices,
discovery_info=None) -> None: discovery_info=None) -> None:
"""Initialize grouped_light platform.""" """Initialize light.group platform."""
async_add_devices([GroupedLight( async_add_devices(
hass, [GroupLight(hass, config.get(CONF_NAME), config[CONF_ENTITIES])])
config.get(CONF_NAME),
config.get(CONF_ENTITIES)
)])
T = TypeVar('T') class GroupLight(light.Light):
"""Representation of a group light."""
class GroupedLight(light.Light):
"""Representation of a Grouped Light."""
def __init__(self, hass: HomeAssistantType, name: str, def __init__(self, hass: HomeAssistantType, name: str,
entity_ids: List[str]) -> None: entity_ids: List[str]) -> None:
"""Initialize a Grouped Light.""" """Initialize a group light."""
self.hass = hass # type: HomeAssistantType self.hass = hass # type: HomeAssistantType
self._name = name # type: str self._name = name # type: str
self._entity_ids = entity_ids # type: List[str] self._entity_ids = entity_ids # type: List[str]
self._state = STATE_OFF # type: str self._state = STATE_UNAVAILABLE # type: str
self._brightness = None # type: Optional[int] self._brightness = None # type: Optional[int]
self._xy_color = None # type: Optional[Tuple[float, float]] self._xy_color = None # type: Optional[Tuple[float, float]]
self._rgb_color = None # type: Optional[Tuple[int, int, int]] self._rgb_color = None # type: Optional[Tuple[int, int, int]]
@@ -78,9 +74,24 @@ class GroupedLight(light.Light):
@asyncio.coroutine @asyncio.coroutine
def async_added_to_hass(self) -> None: def async_added_to_hass(self) -> None:
"""Subscribe to light events.""" """Register callbacks"""
async_track_state_change(self.hass, self._entity_ids,
self._async_state_changed_listener) @callback
def async_state_changed_listener(self, entity_id: str,
old_state: State, new_state: State):
"""Handle child updates."""
self.async_schedule_update_ha_state(True)
@callback
def async_homeassistant_start(event):
"""Track child state changes on startup."""
async_track_state_change(self.hass, self._entity_ids,
async_state_changed_listener)
self.async_schedule_update_ha_state(True)
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_START,
async_homeassistant_start)
@property @property
def name(self) -> str: def name(self) -> str:
@@ -149,7 +160,7 @@ class GroupedLight(light.Light):
@property @property
def should_poll(self) -> bool: def should_poll(self) -> bool:
"""No polling needed for a Grouped Light.""" """No polling needed for a group light."""
return False return False
@asyncio.coroutine @asyncio.coroutine
@@ -208,29 +219,15 @@ class GroupedLight(light.Light):
# so that we don't break in the future when a new feature is added. # so that we don't break in the future when a new feature is added.
self._supported_features &= SUPPORT_GROUP_LIGHT self._supported_features &= SUPPORT_GROUP_LIGHT
@asyncio.coroutine
def _async_state_changed_listener(self, entity_id: str, old_state: State,
new_state: State):
"""Respond to a member state changing."""
yield from self._update_hass()
def _child_states(self) -> List[State]: def _child_states(self) -> List[State]:
"""The states that the group is tracking.""" """The states that the group is tracking."""
states = [self.hass.states.get(x) for x in self._entity_ids] states = [self.hass.states.get(x) for x in self._entity_ids]
return list(filter(None, states)) return list(filter(None, states))
@asyncio.coroutine
def _update_hass(self):
"""Request new status and push it to hass."""
yield from self.async_update()
yield from self.async_update_ha_state()
# https://github.com/PyCQA/pylint/issues/1543
# pylint: disable=bad-whitespace
def _find_state_attributes(states: List[State], def _find_state_attributes(states: List[State],
key: str, key: str,
force_on: bool = True) -> Iterator[T]: force_on: bool = True) -> Iterator[Any]:
"""Find attributes with matching key from states. """Find attributes with matching key from states.
Only returns attributes of enabled lights when force_on is True. Only returns attributes of enabled lights when force_on is True.
@@ -241,12 +238,10 @@ def _find_state_attributes(states: List[State],
yield state.attributes.get(key) yield state.attributes.get(key)
# https://github.com/PyCQA/pylint/issues/1543
# pylint: disable=bad-whitespace
def _reduce_attribute(states: List[State], def _reduce_attribute(states: List[State],
key: str, key: str,
default: Optional[T] = None, default: Optional[Any] = None,
force_on: bool = True) -> T: force_on: bool = True) -> Any:
"""Find the first attribute matching key from states. """Find the first attribute matching key from states.
If none are found, returns default. If none are found, returns default.
@@ -258,12 +253,10 @@ def _determine_on_off_state(states: List[State]) -> str:
"""Helper method to determine the ON/OFF/... state of a light.""" """Helper method to determine the ON/OFF/... state of a light."""
s_states = [state.state for state in states] s_states = [state.state for state in states]
if not s_states: if not s_states or all(state == STATE_UNAVAILABLE for state in s_states):
return STATE_UNAVAILABLE return STATE_UNAVAILABLE
elif any(state == STATE_ON for state in s_states): elif any(state == STATE_ON for state in s_states):
return STATE_ON return STATE_ON
elif all(state == STATE_UNAVAILABLE for state in s_states):
return STATE_UNAVAILABLE
elif all(state == STATE_UNKNOWN for state in s_states): elif all(state == STATE_UNKNOWN for state in s_states):
return STATE_UNKNOWN return STATE_UNKNOWN
return STATE_OFF return STATE_OFF