Remove states UI options in group integration (#32021)
This commit is contained in:
parent
7e3841e172
commit
2ad1f7fd02
4 changed files with 14 additions and 223 deletions
|
@ -30,7 +30,6 @@ from homeassistant.const import (
|
|||
)
|
||||
from homeassistant.core import callback
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.config_validation import make_entity_service_schema
|
||||
from homeassistant.helpers.entity import Entity, async_generate_entity_id
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
from homeassistant.helpers.event import async_track_state_change
|
||||
|
@ -44,26 +43,18 @@ DOMAIN = "group"
|
|||
ENTITY_ID_FORMAT = DOMAIN + ".{}"
|
||||
|
||||
CONF_ENTITIES = "entities"
|
||||
CONF_VIEW = "view"
|
||||
CONF_CONTROL = "control"
|
||||
CONF_ALL = "all"
|
||||
|
||||
ATTR_ADD_ENTITIES = "add_entities"
|
||||
ATTR_AUTO = "auto"
|
||||
ATTR_CONTROL = "control"
|
||||
ATTR_ENTITIES = "entities"
|
||||
ATTR_OBJECT_ID = "object_id"
|
||||
ATTR_ORDER = "order"
|
||||
ATTR_VIEW = "view"
|
||||
ATTR_VISIBLE = "visible"
|
||||
ATTR_ALL = "all"
|
||||
|
||||
SERVICE_SET_VISIBILITY = "set_visibility"
|
||||
SERVICE_SET = "set"
|
||||
SERVICE_REMOVE = "remove"
|
||||
|
||||
CONTROL_TYPES = vol.In(["hidden", None])
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -76,15 +67,11 @@ def _conf_preprocess(value):
|
|||
|
||||
|
||||
GROUP_SCHEMA = vol.All(
|
||||
cv.deprecated(CONF_CONTROL, invalidation_version="0.107.0"),
|
||||
cv.deprecated(CONF_VIEW, invalidation_version="0.107.0"),
|
||||
vol.Schema(
|
||||
{
|
||||
vol.Optional(CONF_ENTITIES): vol.Any(cv.entity_ids, None),
|
||||
CONF_VIEW: cv.boolean,
|
||||
CONF_NAME: cv.string,
|
||||
CONF_ICON: cv.icon,
|
||||
CONF_CONTROL: CONTROL_TYPES,
|
||||
CONF_ALL: cv.boolean,
|
||||
}
|
||||
),
|
||||
|
@ -257,7 +244,7 @@ async def async_setup(hass, config):
|
|||
|
||||
extra_arg = {
|
||||
attr: service.data[attr]
|
||||
for attr in (ATTR_VISIBLE, ATTR_ICON, ATTR_VIEW, ATTR_CONTROL)
|
||||
for attr in (ATTR_ICON)
|
||||
if service.data.get(attr) is not None
|
||||
}
|
||||
|
||||
|
@ -293,22 +280,10 @@ async def async_setup(hass, config):
|
|||
group.name = service.data[ATTR_NAME]
|
||||
need_update = True
|
||||
|
||||
if ATTR_VISIBLE in service.data:
|
||||
group.visible = service.data[ATTR_VISIBLE]
|
||||
need_update = True
|
||||
|
||||
if ATTR_ICON in service.data:
|
||||
group.icon = service.data[ATTR_ICON]
|
||||
need_update = True
|
||||
|
||||
if ATTR_CONTROL in service.data:
|
||||
group.control = service.data[ATTR_CONTROL]
|
||||
need_update = True
|
||||
|
||||
if ATTR_VIEW in service.data:
|
||||
group.view = service.data[ATTR_VIEW]
|
||||
need_update = True
|
||||
|
||||
if ATTR_ALL in service.data:
|
||||
group.mode = all if service.data[ATTR_ALL] else any
|
||||
need_update = True
|
||||
|
@ -327,17 +302,11 @@ async def async_setup(hass, config):
|
|||
SERVICE_SET,
|
||||
locked_service_handler,
|
||||
schema=vol.All(
|
||||
cv.deprecated(ATTR_CONTROL, invalidation_version="0.107.0"),
|
||||
cv.deprecated(ATTR_VIEW, invalidation_version="0.107.0"),
|
||||
cv.deprecated(ATTR_VISIBLE, invalidation_version="0.107.0"),
|
||||
vol.Schema(
|
||||
{
|
||||
vol.Required(ATTR_OBJECT_ID): cv.slug,
|
||||
vol.Optional(ATTR_NAME): cv.string,
|
||||
vol.Optional(ATTR_VIEW): cv.boolean,
|
||||
vol.Optional(ATTR_ICON): cv.string,
|
||||
vol.Optional(ATTR_CONTROL): CONTROL_TYPES,
|
||||
vol.Optional(ATTR_VISIBLE): cv.boolean,
|
||||
vol.Optional(ATTR_ALL): cv.boolean,
|
||||
vol.Exclusive(ATTR_ENTITIES, "entities"): cv.entity_ids,
|
||||
vol.Exclusive(ATTR_ADD_ENTITIES, "entities"): cv.entity_ids,
|
||||
|
@ -353,32 +322,6 @@ async def async_setup(hass, config):
|
|||
schema=vol.Schema({vol.Required(ATTR_OBJECT_ID): cv.slug}),
|
||||
)
|
||||
|
||||
async def visibility_service_handler(service):
|
||||
"""Change visibility of a group."""
|
||||
visible = service.data.get(ATTR_VISIBLE)
|
||||
|
||||
_LOGGER.warning(
|
||||
"The group.set_visibility service has been deprecated and will"
|
||||
"be removed in Home Assistant 0.107.0."
|
||||
)
|
||||
|
||||
tasks = []
|
||||
for group in await component.async_extract_from_service(
|
||||
service, expand_group=False
|
||||
):
|
||||
group.visible = visible
|
||||
tasks.append(group.async_update_ha_state())
|
||||
|
||||
if tasks:
|
||||
await asyncio.wait(tasks)
|
||||
|
||||
hass.services.async_register(
|
||||
DOMAIN,
|
||||
SERVICE_SET_VISIBILITY,
|
||||
visibility_service_handler,
|
||||
schema=make_entity_service_schema({vol.Required(ATTR_VISIBLE): cv.boolean}),
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
@ -388,21 +331,12 @@ async def _async_process_config(hass, config, component):
|
|||
name = conf.get(CONF_NAME, object_id)
|
||||
entity_ids = conf.get(CONF_ENTITIES) or []
|
||||
icon = conf.get(CONF_ICON)
|
||||
view = conf.get(CONF_VIEW)
|
||||
control = conf.get(CONF_CONTROL)
|
||||
mode = conf.get(CONF_ALL)
|
||||
|
||||
# Don't create tasks and await them all. The order is important as
|
||||
# groups get a number based on creation order.
|
||||
await Group.async_create_group(
|
||||
hass,
|
||||
name,
|
||||
entity_ids,
|
||||
icon=icon,
|
||||
view=view,
|
||||
control=control,
|
||||
object_id=object_id,
|
||||
mode=mode,
|
||||
hass, name, entity_ids, icon=icon, object_id=object_id, mode=mode,
|
||||
)
|
||||
|
||||
|
||||
|
@ -414,10 +348,7 @@ class Group(Entity):
|
|||
hass,
|
||||
name,
|
||||
order=None,
|
||||
visible=True,
|
||||
icon=None,
|
||||
view=False,
|
||||
control=None,
|
||||
user_defined=True,
|
||||
entity_ids=None,
|
||||
mode=None,
|
||||
|
@ -430,15 +361,12 @@ class Group(Entity):
|
|||
self._name = name
|
||||
self._state = STATE_UNKNOWN
|
||||
self._icon = icon
|
||||
self.view = view
|
||||
if entity_ids:
|
||||
self.tracking = tuple(ent_id.lower() for ent_id in entity_ids)
|
||||
else:
|
||||
self.tracking = tuple()
|
||||
self.group_on = None
|
||||
self.group_off = None
|
||||
self.visible = visible
|
||||
self.control = control
|
||||
self.user_defined = user_defined
|
||||
self.mode = any
|
||||
if mode:
|
||||
|
@ -453,26 +381,14 @@ class Group(Entity):
|
|||
name,
|
||||
entity_ids=None,
|
||||
user_defined=True,
|
||||
visible=True,
|
||||
icon=None,
|
||||
view=False,
|
||||
control=None,
|
||||
object_id=None,
|
||||
mode=None,
|
||||
):
|
||||
"""Initialize a group."""
|
||||
return asyncio.run_coroutine_threadsafe(
|
||||
Group.async_create_group(
|
||||
hass,
|
||||
name,
|
||||
entity_ids,
|
||||
user_defined,
|
||||
visible,
|
||||
icon,
|
||||
view,
|
||||
control,
|
||||
object_id,
|
||||
mode,
|
||||
hass, name, entity_ids, user_defined, icon, object_id, mode,
|
||||
),
|
||||
hass.loop,
|
||||
).result()
|
||||
|
@ -483,10 +399,7 @@ class Group(Entity):
|
|||
name,
|
||||
entity_ids=None,
|
||||
user_defined=True,
|
||||
visible=True,
|
||||
icon=None,
|
||||
view=False,
|
||||
control=None,
|
||||
object_id=None,
|
||||
mode=None,
|
||||
):
|
||||
|
@ -498,10 +411,7 @@ class Group(Entity):
|
|||
hass,
|
||||
name,
|
||||
order=len(hass.states.async_entity_ids(DOMAIN)),
|
||||
visible=visible,
|
||||
icon=icon,
|
||||
view=view,
|
||||
control=control,
|
||||
user_defined=user_defined,
|
||||
entity_ids=entity_ids,
|
||||
mode=mode,
|
||||
|
@ -551,23 +461,12 @@ class Group(Entity):
|
|||
"""Set Icon for group."""
|
||||
self._icon = value
|
||||
|
||||
@property
|
||||
def hidden(self):
|
||||
"""If group should be hidden or not."""
|
||||
if self.visible and not self.view:
|
||||
return False
|
||||
return True
|
||||
|
||||
@property
|
||||
def state_attributes(self):
|
||||
"""Return the state attributes for the group."""
|
||||
data = {ATTR_ENTITY_ID: self.tracking, ATTR_ORDER: self._order}
|
||||
if not self.user_defined:
|
||||
data[ATTR_AUTO] = True
|
||||
if self.view:
|
||||
data[ATTR_VIEW] = True
|
||||
if self.control:
|
||||
data[ATTR_CONTROL] = self.control
|
||||
return data
|
||||
|
||||
@property
|
||||
|
|
|
@ -3,37 +3,18 @@
|
|||
reload:
|
||||
description: Reload group configuration.
|
||||
|
||||
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
|
||||
|
||||
set:
|
||||
description: Create/Update a user group.
|
||||
fields:
|
||||
object_id:
|
||||
description: Group id and part of entity id.
|
||||
example: 'test_group'
|
||||
example: "test_group"
|
||||
name:
|
||||
description: Name of group
|
||||
example: 'My test group'
|
||||
view:
|
||||
description: Boolean for if the group is a view.
|
||||
example: True
|
||||
example: "My test group"
|
||||
icon:
|
||||
description: Name of icon for the group.
|
||||
example: 'mdi:camera'
|
||||
control:
|
||||
description: Value for control the group control.
|
||||
example: 'hidden'
|
||||
visible:
|
||||
description: If the group is visible on UI.
|
||||
example: True
|
||||
example: "mdi:camera"
|
||||
entities:
|
||||
description: List of all members in the group. Not compatible with 'delta'.
|
||||
example: domain.entity_id1, domain.entity_id2
|
||||
|
@ -49,5 +30,4 @@ remove:
|
|||
fields:
|
||||
object_id:
|
||||
description: Group id and part of entity id.
|
||||
example: 'test_group'
|
||||
|
||||
example: "test_group"
|
||||
|
|
|
@ -5,17 +5,13 @@ components. Instead call the service directly.
|
|||
"""
|
||||
from homeassistant.components.group import (
|
||||
ATTR_ADD_ENTITIES,
|
||||
ATTR_CONTROL,
|
||||
ATTR_ENTITIES,
|
||||
ATTR_OBJECT_ID,
|
||||
ATTR_VIEW,
|
||||
ATTR_VISIBLE,
|
||||
DOMAIN,
|
||||
SERVICE_REMOVE,
|
||||
SERVICE_SET,
|
||||
SERVICE_SET_VISIBILITY,
|
||||
)
|
||||
from homeassistant.const import ATTR_ENTITY_ID, ATTR_ICON, ATTR_NAME, SERVICE_RELOAD
|
||||
from homeassistant.const import ATTR_ICON, ATTR_NAME, SERVICE_RELOAD
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.loader import bind_hass
|
||||
|
||||
|
@ -35,43 +31,18 @@ def async_reload(hass):
|
|||
|
||||
@bind_hass
|
||||
def set_group(
|
||||
hass,
|
||||
object_id,
|
||||
name=None,
|
||||
entity_ids=None,
|
||||
visible=None,
|
||||
icon=None,
|
||||
view=None,
|
||||
control=None,
|
||||
add=None,
|
||||
hass, object_id, name=None, entity_ids=None, icon=None, add=None,
|
||||
):
|
||||
"""Create/Update a group."""
|
||||
hass.add_job(
|
||||
async_set_group,
|
||||
hass,
|
||||
object_id,
|
||||
name,
|
||||
entity_ids,
|
||||
visible,
|
||||
icon,
|
||||
view,
|
||||
control,
|
||||
add,
|
||||
async_set_group, hass, object_id, name, entity_ids, icon, add,
|
||||
)
|
||||
|
||||
|
||||
@callback
|
||||
@bind_hass
|
||||
def async_set_group(
|
||||
hass,
|
||||
object_id,
|
||||
name=None,
|
||||
entity_ids=None,
|
||||
visible=None,
|
||||
icon=None,
|
||||
view=None,
|
||||
control=None,
|
||||
add=None,
|
||||
hass, object_id, name=None, entity_ids=None, icon=None, add=None,
|
||||
):
|
||||
"""Create/Update a group."""
|
||||
data = {
|
||||
|
@ -80,10 +51,7 @@ def async_set_group(
|
|||
(ATTR_OBJECT_ID, object_id),
|
||||
(ATTR_NAME, name),
|
||||
(ATTR_ENTITIES, entity_ids),
|
||||
(ATTR_VISIBLE, visible),
|
||||
(ATTR_ICON, icon),
|
||||
(ATTR_VIEW, view),
|
||||
(ATTR_CONTROL, control),
|
||||
(ATTR_ADD_ENTITIES, add),
|
||||
]
|
||||
if value is not None
|
||||
|
@ -98,10 +66,3 @@ def async_remove(hass, object_id):
|
|||
"""Remove a user group."""
|
||||
data = {ATTR_OBJECT_ID: object_id}
|
||||
hass.async_add_job(hass.services.async_call(DOMAIN, SERVICE_REMOVE, data))
|
||||
|
||||
|
||||
@bind_hass
|
||||
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)
|
||||
|
|
|
@ -8,7 +8,6 @@ import homeassistant.components.group as group
|
|||
from homeassistant.const import (
|
||||
ATTR_ASSUMED_STATE,
|
||||
ATTR_FRIENDLY_NAME,
|
||||
ATTR_HIDDEN,
|
||||
ATTR_ICON,
|
||||
STATE_HOME,
|
||||
STATE_NOT_HOME,
|
||||
|
@ -291,8 +290,6 @@ class TestComponentsGroup(unittest.TestCase):
|
|||
group_conf["second_group"] = {
|
||||
"entities": "light.Bowl, " + test_group.entity_id,
|
||||
"icon": "mdi:work",
|
||||
"view": True,
|
||||
"control": "hidden",
|
||||
}
|
||||
group_conf["test_group"] = "hello.world,sensor.happy"
|
||||
group_conf["empty_group"] = {"name": "Empty Group", "entities": None}
|
||||
|
@ -308,9 +305,6 @@ class TestComponentsGroup(unittest.TestCase):
|
|||
)
|
||||
assert group_state.attributes.get(group.ATTR_AUTO) is None
|
||||
assert "mdi:work" == group_state.attributes.get(ATTR_ICON)
|
||||
assert group_state.attributes.get(group.ATTR_VIEW)
|
||||
assert "hidden" == group_state.attributes.get(group.ATTR_CONTROL)
|
||||
assert group_state.attributes.get(ATTR_HIDDEN)
|
||||
assert 1 == group_state.attributes.get(group.ATTR_ORDER)
|
||||
|
||||
group_state = self.hass.states.get(group.ENTITY_ID_FORMAT.format("test_group"))
|
||||
|
@ -320,9 +314,6 @@ class TestComponentsGroup(unittest.TestCase):
|
|||
)
|
||||
assert group_state.attributes.get(group.ATTR_AUTO) is None
|
||||
assert group_state.attributes.get(ATTR_ICON) is None
|
||||
assert group_state.attributes.get(group.ATTR_VIEW) is None
|
||||
assert group_state.attributes.get(group.ATTR_CONTROL) is None
|
||||
assert group_state.attributes.get(ATTR_HIDDEN) is None
|
||||
assert 2 == group_state.attributes.get(group.ATTR_ORDER)
|
||||
|
||||
def test_groups_get_unique_names(self):
|
||||
|
@ -394,11 +385,7 @@ class TestComponentsGroup(unittest.TestCase):
|
|||
"group",
|
||||
{
|
||||
"group": {
|
||||
"second_group": {
|
||||
"entities": "light.Bowl",
|
||||
"icon": "mdi:work",
|
||||
"view": True,
|
||||
},
|
||||
"second_group": {"entities": "light.Bowl", "icon": "mdi:work"},
|
||||
"test_group": "hello.world,sensor.happy",
|
||||
"empty_group": {"name": "Empty Group", "entities": None},
|
||||
}
|
||||
|
@ -420,13 +407,7 @@ class TestComponentsGroup(unittest.TestCase):
|
|||
with patch(
|
||||
"homeassistant.config.load_yaml_config_file",
|
||||
return_value={
|
||||
"group": {
|
||||
"hello": {
|
||||
"entities": "light.Bowl",
|
||||
"icon": "mdi:work",
|
||||
"view": True,
|
||||
}
|
||||
}
|
||||
"group": {"hello": {"entities": "light.Bowl", "icon": "mdi:work"}}
|
||||
},
|
||||
):
|
||||
common.reload(self.hass)
|
||||
|
@ -438,26 +419,6 @@ class TestComponentsGroup(unittest.TestCase):
|
|||
]
|
||||
assert self.hass.bus.listeners["state_changed"] == 2
|
||||
|
||||
def test_changing_group_visibility(self):
|
||||
"""Test that a group can be hidden and shown."""
|
||||
assert 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
|
||||
common.set_visibility(self.hass, group_entity_id, False)
|
||||
self.hass.block_till_done()
|
||||
group_state = self.hass.states.get(group_entity_id)
|
||||
assert group_state.attributes.get(ATTR_HIDDEN)
|
||||
|
||||
# Show it again
|
||||
common.set_visibility(self.hass, group_entity_id, True)
|
||||
self.hass.block_till_done()
|
||||
group_state = self.hass.states.get(group_entity_id)
|
||||
assert group_state.attributes.get(ATTR_HIDDEN) is None
|
||||
|
||||
def test_modify_group(self):
|
||||
"""Test modifying a group."""
|
||||
group_conf = OrderedDict()
|
||||
|
@ -503,19 +464,13 @@ async def test_service_group_set_group_remove_group(hass):
|
|||
assert group_state.attributes["friendly_name"] == "Test"
|
||||
|
||||
common.async_set_group(
|
||||
hass,
|
||||
"user_test_group",
|
||||
view=True,
|
||||
visible=False,
|
||||
entity_ids=["test.entity_bla1"],
|
||||
hass, "user_test_group", entity_ids=["test.entity_bla1"],
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
group_state = hass.states.get("group.user_test_group")
|
||||
assert group_state
|
||||
assert group_state.attributes[group.ATTR_VIEW]
|
||||
assert group_state.attributes[group.ATTR_AUTO]
|
||||
assert group_state.attributes["hidden"]
|
||||
assert group_state.attributes["friendly_name"] == "Test"
|
||||
assert list(group_state.attributes["entity_id"]) == ["test.entity_bla1"]
|
||||
|
||||
|
@ -524,19 +479,15 @@ async def test_service_group_set_group_remove_group(hass):
|
|||
"user_test_group",
|
||||
icon="mdi:camera",
|
||||
name="Test2",
|
||||
control="hidden",
|
||||
add=["test.entity_id2"],
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
group_state = hass.states.get("group.user_test_group")
|
||||
assert group_state
|
||||
assert group_state.attributes[group.ATTR_VIEW]
|
||||
assert group_state.attributes[group.ATTR_AUTO]
|
||||
assert group_state.attributes["hidden"]
|
||||
assert group_state.attributes["friendly_name"] == "Test2"
|
||||
assert group_state.attributes["icon"] == "mdi:camera"
|
||||
assert group_state.attributes[group.ATTR_CONTROL] == "hidden"
|
||||
assert sorted(list(group_state.attributes["entity_id"])) == sorted(
|
||||
["test.entity_bla1", "test.entity_id2"]
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue