Last active
December 22, 2020 20:15
-
-
Save randellhodges/96a0cd9bafa03fb90ada49040d65f1b0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
@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'
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@crazybadger: Just got this working as follows:
configuration.yaml
groups.yaml
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.