-
-
Save randellhodges/96a0cd9bafa03fb90ada49040d65f1b0 to your computer and use it in GitHub Desktop.
In the directory your configuration.yaml file is location, create a folder called custom_components and put group_globber.py there. Then inside your configuration.yaml file, add a section like so: | |
group_globber: | |
groups: | |
group.group_emby: | |
- media_player.emby* | |
You should probably already have the group, in this case "group_emby" already created somewhere. Then you can add a list of wildcards that'll match entities and put them in that group. | |
Note: I have not tried modifying the built in "all" groups and I have always had the group I want to add things to already created. |
import asyncio | |
import fnmatch | |
import re | |
import logging | |
import voluptuous as vol | |
from homeassistant.helpers import config_validation as cv | |
from homeassistant.const import ( | |
EVENT_STATE_CHANGED) | |
from homeassistant.components import ( | |
group) | |
import homeassistant.core as ha | |
DOMAIN = 'group_globber' | |
_LOGGER = logging.getLogger(__name__) | |
CONF_GROUPS = 'groups' | |
CONFIG_SCHEMA = vol.Schema({ | |
DOMAIN: vol.Schema({ | |
vol.Required(CONF_GROUPS): vol.Schema({ | |
str: vol.Schema(vol.All(cv.ensure_list, [cv.string])) | |
}) | |
}) | |
}, extra=vol.ALLOW_EXTRA) | |
@asyncio.coroutine | |
def async_setup(hass, config): | |
#lock = threading.Lock() | |
config = config.get(DOMAIN) | |
groups = config.get(CONF_GROUPS) | |
# We are going to keep track of what we see, so we don't have to check the groups | |
# on every state update. | |
seen = set() | |
for key, value in groups.items(): | |
groups[key] = [re.compile(fnmatch.translate(x)) for x in value] | |
@ha.callback | |
def _handle_state_change(event): | |
entity_id = event.data.get('entity_id') | |
domain, object_id = ha.split_entity_id(entity_id) | |
if domain == 'group': | |
# Newly created group won't have an old_state | |
is_new = event.data.get('old_state') is None | |
if is_new: | |
#_LOGGER.debug("Group %s created", entity_id) | |
group_id = entity_id | |
expressions = groups.get(group_id) | |
if expressions: | |
# We have to get all the items and then see if they match. Seems | |
# like it could be rather expensive if we had a lot of groups created (reloaded). | |
# Maybe I'm micro-optimizing... | |
for entity_id in hass.states.async_entity_ids(): | |
seen.add(entity_id) | |
if any(x.match(entity_id) for x in expressions): | |
_LOGGER.debug("Adding %s to group %s (reload)", entity_id, group_id) | |
group.set_group(hass, object_id, add=[entity_id]) | |
else: | |
# Check that we have a state. If it isn't there, that means it is a | |
# probably being removed | |
new_state = event.data.get('new_state') | |
if new_state: | |
if not entity_id in seen: | |
seen.add(entity_id) | |
for group_id, expressions in groups.items(): | |
if any(x.match(entity_id) for x in expressions): | |
_LOGGER.debug("Adding %s to group %s (state_change)", entity_id, group_id) | |
_, object_id = ha.split_entity_id(group_id) | |
group.set_group(hass, object_id, add=[entity_id]) | |
return | |
# If we get here, that means we didn't have a new_state, so that means it was removed | |
if entity_id in seen: | |
seen.remove(entity_id) | |
hass.bus.async_listen(EVENT_STATE_CHANGED, _handle_state_change) | |
return True |
@crazybadger: Just got this working as follows:
configuration.yaml
...
group_globber:
groups:
group.all_media_players:
- media_player.*
...
group: !include groups.yaml
groups.yaml
all_media_players:
name: 'All Media Players'
entities:
- media_player.xboxone_2
Note: I added a single already-existing media player, because I suspected home assistant might be reluctant to create an empty group. I did not test this, however.
@randellhodges
Thank you, this grouped them without issue.
To go further; how would one create an automation based on any media player playing or paused?
From what I can see, group state seems to be reflective of all entities within the group (all_lights
only has a state of on
when all the lights are on).
I'd like to trigger lights off when any single media player (or combination of media players) turns on.
I think this broke in 0.80? No?
I think so... I'm now at 0.84.6. I can see the following error in the HA log.
2018-12-31 00:41:01 ERROR (MainThread) [homeassistant.core] Error doing job: Exception in callback async_setup.<locals>._handle_state_change(<Event state_...binihomelocal>) at /opt/homeassistant/.homeassistant/custom_components/group_globber.py:45
Traceback (most recent call last):
File "/usr/lib/python3.5/asyncio/events.py", line 126, in _run
self._callback(*self._args)
File "/opt/homeassistant/.homeassistant/custom_components/group_globber.py", line 84, in _handle_state_change
group.set_group(hass, object_id, add=[entity_id])
AttributeError: module 'homeassistant.components.group' has no attribute 'set_group'
This sounds like just what I was looking for - a way to group all emby entities - but I'm struggling to get it working.
I've created the sub-folder called custom_components and created the group_globber.py file with the code above.
I've added the group_globber: code to the bottom of my configuration.yaml file and I've created a group_emby in my group.yaml file which looks like this:
group_emby:
name: emby
view: yes
entities:
-media_player.emby*
But I'm getting invalid config on my group. What am I doing wrong?