1
mirror of https://github.com/home-assistant/core synced 2024-07-30 21:18:57 +02:00

Add service to change visibility of a group (#3998)

This commit is contained in:
Pierre Ståhl 2016-10-30 01:54:26 +02:00 committed by Paulus Schoutsen
parent 3f6a5564ad
commit 33e46b484f
7 changed files with 106 additions and 9 deletions

View File

@ -33,6 +33,13 @@ CONF_VIEW = 'view'
ATTR_AUTO = 'auto'
ATTR_ORDER = 'order'
ATTR_VIEW = 'view'
ATTR_VISIBLE = 'visible'
SERVICE_SET_VISIBILITY = 'set_visibility'
SET_VISIBILITY_SERVICE_SCHEMA = vol.Schema({
vol.Optional(ATTR_ENTITY_ID): cv.entity_ids,
vol.Required(ATTR_VISIBLE): cv.boolean
})
SERVICE_RELOAD = 'reload'
RELOAD_SERVICE_SCHEMA = vol.Schema({})
@ -89,6 +96,12 @@ def reload(hass):
hass.services.call(DOMAIN, SERVICE_RELOAD)
def set_visibility(hass, entity_id=None, visible=True):
"""Hide or shows a group."""
data = {ATTR_ENTITY_ID: entity_id, ATTR_VISIBLE: visible}
hass.services.call(DOMAIN, SERVICE_SET_VISIBILITY, data)
def expand_entity_ids(hass, entity_ids):
"""Return entity_ids with group entity ids replaced by their members.
@ -164,6 +177,18 @@ def async_setup(hass, config):
return
hass.loop.create_task(_async_process_config(hass, conf, component))
@callback
def visibility_service_handler(service):
"""Change visibility of a group."""
visible = service.data.get(ATTR_VISIBLE)
for group in component.async_extract_from_service(
service, expand_group=False):
group.async_set_visible(visible)
hass.services.async_register(
DOMAIN, SERVICE_SET_VISIBILITY, visibility_service_handler,
descriptions[DOMAIN][SERVICE_SET_VISIBILITY],
schema=SET_VISIBILITY_SERVICE_SCHEMA)
hass.services.async_register(
DOMAIN, SERVICE_RELOAD, reload_service_handler,
descriptions[DOMAIN][SERVICE_RELOAD], schema=RELOAD_SERVICE_SCHEMA)
@ -212,6 +237,7 @@ class Group(Entity):
self.group_off = None
self._assumed_state = False
self._async_unsub_state_changed = None
self._visible = True
@staticmethod
# pylint: disable=too-many-arguments
@ -268,10 +294,20 @@ class Group(Entity):
"""Return the icon of the group."""
return self._icon
@callback
def async_set_visible(self, visible):
"""Change visibility of the group."""
if self._visible != visible:
self._visible = visible
self.hass.loop.create_task(self.async_update_ha_state())
@property
def hidden(self):
"""If group should be hidden or not."""
return not self._user_defined or self._view
# Visibility from set_visibility service overrides
if self._visible:
return not self._user_defined or self._view
return True
@property
def state_attributes(self):

View File

@ -44,6 +44,18 @@ group:
description: "Reload group configuration."
fields:
set_visibility:
description: Hide or show a group
fields:
entity_id:
description: Name(s) of entities to set value
example: 'group.travel'
visible:
description: True if group should be shown or False if it should be hidden.
example: True
persistent_notification:
create:
description: Show a notification in the frontend

View File

@ -86,17 +86,18 @@ class EntityComponent(object):
discovery.async_listen_platform(
self.hass, self.domain, component_platform_discovered)
def extract_from_service(self, service):
def extract_from_service(self, service, expand_group=True):
"""Extract all known entities from a service call.
Will return all entities if no entities specified in call.
Will return an empty list if entities specified but unknown.
"""
return run_callback_threadsafe(
self.hass.loop, self.async_extract_from_service, service
self.hass.loop, self.async_extract_from_service, service,
expand_group
).result()
def async_extract_from_service(self, service):
def async_extract_from_service(self, service, expand_group=True):
"""Extract all known entities from a service call.
Will return all entities if no entities specified in call.
@ -108,7 +109,7 @@ class EntityComponent(object):
return list(self.entities.values())
return [self.entities[entity_id] for entity_id
in extract_entity_ids(self.hass, service)
in extract_entity_ids(self.hass, service, expand_group)
if entity_id in self.entities]
@asyncio.coroutine

View File

@ -94,7 +94,7 @@ def async_call_from_config(hass, config, blocking=False, variables=None,
domain, service_name, service_data, blocking)
def extract_entity_ids(hass, service_call):
def extract_entity_ids(hass, service_call, expand_group=True):
"""Helper method to extract a list of entity ids from a service call.
Will convert group entity ids to the entity ids it represents.
@ -109,7 +109,17 @@ def extract_entity_ids(hass, service_call):
# Entity ID attr can be a list or a string
service_ent_id = service_call.data[ATTR_ENTITY_ID]
if isinstance(service_ent_id, str):
return group.expand_entity_ids(hass, [service_ent_id])
if expand_group:
return [ent_id for ent_id in group.expand_entity_ids(hass, service_ent_id)]
if isinstance(service_ent_id, str):
return group.expand_entity_ids(hass, [service_ent_id])
return [ent_id for ent_id in
group.expand_entity_ids(hass, service_ent_id)]
else:
if isinstance(service_ent_id, str):
return [service_ent_id]
return service_ent_id

View File

@ -352,3 +352,23 @@ class TestComponentsGroup(unittest.TestCase):
assert self.hass.states.entity_ids() == ['group.light']
grp.stop()
assert self.hass.states.entity_ids() == []
def test_changing_group_visibility(self):
"""Test that a group can be hidden and shown."""
setup_component(self.hass, 'group', {
'group': {
'test_group': 'hello.world,sensor.happy'
}
})
group_entity_id = group.ENTITY_ID_FORMAT.format('test_group')
# Hide the group
group.set_visibility(self.hass, group_entity_id, False)
group_state = self.hass.states.get(group_entity_id)
self.assertTrue(group_state.attributes.get(ATTR_HIDDEN))
# Show it again
group.set_visibility(self.hass, group_entity_id, True)
group_state = self.hass.states.get(group_entity_id)
self.assertIsNone(group_state.attributes.get(ATTR_HIDDEN))

View File

@ -7,6 +7,7 @@ from unittest.mock import patch, Mock
import homeassistant.core as ha
import homeassistant.loader as loader
from homeassistant.components import group
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers import discovery
@ -205,6 +206,20 @@ class TestHelpersEntityComponent(unittest.TestCase):
assert ['test_domain.test_2'] == \
[ent.entity_id for ent in component.extract_from_service(call)]
def test_extract_from_service_no_group_expand(self):
"""Test not expanding a group."""
component = EntityComponent(_LOGGER, DOMAIN, self.hass)
test_group = group.Group.create_group(
self.hass, 'test_group', ['light.Ceiling', 'light.Kitchen'])
component.add_entities([test_group])
call = ha.ServiceCall('test', 'service', {
'entity_id': ['group.test_group']
})
extracted = component.extract_from_service(call, expand_group=False)
self.assertEqual([test_group], extracted)
def test_setup_loads_platforms(self):
"""Test the loading of the platforms."""
component_setup = Mock(return_value=True)

View File

@ -153,3 +153,6 @@ class TestServiceHelpers(unittest.TestCase):
self.assertEqual(['light.ceiling', 'light.kitchen'],
service.extract_entity_ids(self.hass, call))
self.assertEqual(['group.test'], service.extract_entity_ids(
self.hass, call, expand_group=False))