Merge pull request #1374 from sander76/scene_with_platforms

scene with platforms
This commit is contained in:
Paulus Schoutsen 2016-02-29 23:00:03 -08:00
commit 4370f5170b
3 changed files with 98 additions and 66 deletions

View File

@ -0,0 +1,85 @@
"""
homeassistant.components.scene
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Allows users to set and activate scenes.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/scene/
"""
import logging
from collections import namedtuple
from homeassistant.const import (
ATTR_ENTITY_ID, SERVICE_TURN_ON, CONF_PLATFORM)
from homeassistant.helpers import extract_domain_configs
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
DOMAIN = 'scene'
DEPENDENCIES = ['group']
STATE = 'scening'
CONF_ENTITIES = "entities"
SceneConfig = namedtuple('SceneConfig', ['name', 'states'])
def activate(hass, entity_id=None):
""" Activate a scene. """
data = {}
if entity_id:
data[ATTR_ENTITY_ID] = entity_id
hass.services.call(DOMAIN, SERVICE_TURN_ON, data)
def setup(hass, config):
""" Sets up scenes. """
logger = logging.getLogger(__name__)
# You are not allowed to mutate the original config so make a copy
config = dict(config)
for config_key in extract_domain_configs(config, DOMAIN):
platform_config = config[config_key]
if not isinstance(platform_config, list):
platform_config = [platform_config]
if not any(CONF_PLATFORM in entry for entry in platform_config):
platform_config = [{'platform': 'homeassistant', 'states': entry}
for entry in platform_config]
config[config_key] = platform_config
component = EntityComponent(logger, DOMAIN, hass)
component.setup(config)
def handle_scene_service(service):
""" Handles calls to the switch services. """
target_scenes = component.extract_from_service(service)
for scene in target_scenes:
scene.activate()
hass.services.register(DOMAIN, SERVICE_TURN_ON, handle_scene_service)
return True
class Scene(Entity):
""" A scene is a group of entities and the states we want them to be. """
@property
def should_poll(self):
return False
@property
def state(self):
return STATE
def activate(self):
""" Activates scene. Tries to get entities into requested state. """
raise NotImplementedError

View File

@ -6,17 +6,14 @@ Allows users to set and activate scenes.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
https://home-assistant.io/components/scene/ https://home-assistant.io/components/scene/
""" """
import logging
from collections import namedtuple from collections import namedtuple
from homeassistant.components.scene import Scene
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, SERVICE_TURN_ON, STATE_OFF, STATE_ON) ATTR_ENTITY_ID, STATE_OFF, STATE_ON)
from homeassistant.core import State from homeassistant.core import State
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.state import reproduce_state from homeassistant.helpers.state import reproduce_state
DOMAIN = 'scene'
DEPENDENCIES = ['group'] DEPENDENCIES = ['group']
STATE = 'scening' STATE = 'scening'
@ -25,41 +22,16 @@ CONF_ENTITIES = "entities"
SceneConfig = namedtuple('SceneConfig', ['name', 'states']) SceneConfig = namedtuple('SceneConfig', ['name', 'states'])
def activate(hass, entity_id=None): # pylint: disable=unused-argument
""" Activate a scene. """ def setup_platform(hass, config, add_devices, discovery_info=None):
data = {} """ Sets up home assistant scene entries. """
scene_config = config.get("states")
if entity_id: if not isinstance(scene_config, list):
data[ATTR_ENTITY_ID] = entity_id scene_config = [scene_config]
hass.services.call(DOMAIN, SERVICE_TURN_ON, data) add_devices(HomeAssistantScene(hass, _process_config(scene))
for scene in scene_config)
def setup(hass, config):
""" Sets up scenes. """
logger = logging.getLogger(__name__)
scene_configs = config.get(DOMAIN)
if not isinstance(scene_configs, list) or \
any(not isinstance(item, dict) for item in scene_configs):
logger.error('Scene config should be a list of dictionaries')
return False
component = EntityComponent(logger, DOMAIN, hass)
component.add_entities(Scene(hass, _process_config(scene_config))
for scene_config in scene_configs)
def handle_scene_service(service):
""" Handles calls to the switch services. """
target_scenes = component.extract_from_service(service)
for scene in target_scenes:
scene.activate()
hass.services.register(DOMAIN, SERVICE_TURN_ON, handle_scene_service)
return True return True
@ -92,37 +64,22 @@ def _process_config(scene_config):
return SceneConfig(name, states) return SceneConfig(name, states)
class Scene(Entity): class HomeAssistantScene(Scene):
""" A scene is a group of entities and the states we want them to be. """ """ A scene is a group of entities and the states we want them to be. """
def __init__(self, hass, scene_config): def __init__(self, hass, scene_config):
self.hass = hass self.hass = hass
self.scene_config = scene_config self.scene_config = scene_config
self.update()
@property
def should_poll(self):
return False
@property @property
def name(self): def name(self):
return self.scene_config.name return self.scene_config.name
@property @property
def state(self): def device_state_attributes(self):
return STATE
@property
def entity_ids(self):
""" Entity IDs part of this scene. """
return self.scene_config.states.keys()
@property
def state_attributes(self):
""" Scene state attributes. """ """ Scene state attributes. """
return { return {
ATTR_ENTITY_ID: list(self.entity_ids), ATTR_ENTITY_ID: list(self.scene_config.states.keys()),
} }
def activate(self): def activate(self):

View File

@ -22,16 +22,6 @@ class TestScene(unittest.TestCase):
""" Stop down stuff we started. """ """ Stop down stuff we started. """
self.hass.stop() self.hass.stop()
def test_config_not_list(self):
self.assertFalse(scene.setup(self.hass, {
'scene': {'some': 'dict'}
}))
def test_config_no_dict_in_list(self):
self.assertFalse(scene.setup(self.hass, {
'scene': [[]]
}))
def test_config_yaml_alias_anchor(self): def test_config_yaml_alias_anchor(self):
""" """
Tests the usage of YAML aliases and anchors. The following test scene Tests the usage of YAML aliases and anchors. The following test scene