* first version
* First draft component entities
* Change add_entities to callback from coroutine
* Fix bug add async_prepare_reload
* Group draft v1
* group async
* bugfix
* bugfix v2
* fix lint
* fix extract_entity_ids
* fix other things
* move get_component out of executor
* bugfix
* Address minor changes
* lint
* bugfix - should work now
* make group init async only
* change update handling to old stuff
* fix group handling, remove generator from init
* fix lint
* protect loop for spaming with updates
* fix lint
* update test_group
* fix
* update group handling
* fix __init__ async trouble
* move device_tracker to new layout
* lint
* fix group unittest
* Test with coroutine
* fix bug
* now it works 💯
* ups
* first part of suggestion
* add_entities to coroutine
* change group
* convert add async_add_entity to coroutine
* fix unit tests
* fix lint
* fix lint part 2
* fix wrong import delete
* change async_update_tracked_entity_ids to coroutine
* fix
* revert last change
* fix unittest entity id
* fix unittest
* fix unittest
* fix unittest entity_component
* fix group
* fix group_test
* try part 2 to fix test_group
* fix all entity_component
* rename _process_config
* Change Group to init with factory
* fix lint
* fix lint
* fix callback
* Tweak entity component and group
* More fixes
* Final fixes
* No longer needed blocks
* Address @bbangert comments
* Add test for group.stop
* More callbacks for automation
106 lines
3.2 KiB
Python
106 lines
3.2 KiB
Python
"""Helper methods to help with platform discovery."""
|
|
|
|
from homeassistant import bootstrap, core
|
|
from homeassistant.const import (
|
|
ATTR_DISCOVERED, ATTR_SERVICE, EVENT_PLATFORM_DISCOVERED)
|
|
from homeassistant.util.async import run_callback_threadsafe
|
|
|
|
EVENT_LOAD_PLATFORM = 'load_platform.{}'
|
|
ATTR_PLATFORM = 'platform'
|
|
|
|
|
|
def listen(hass, service, callback):
|
|
"""Setup listener for discovery of specific service.
|
|
|
|
Service can be a string or a list/tuple.
|
|
"""
|
|
if isinstance(service, str):
|
|
service = (service,)
|
|
else:
|
|
service = tuple(service)
|
|
|
|
def discovery_event_listener(event):
|
|
"""Listen for discovery events."""
|
|
if ATTR_SERVICE in event.data and event.data[ATTR_SERVICE] in service:
|
|
callback(event.data[ATTR_SERVICE], event.data.get(ATTR_DISCOVERED))
|
|
|
|
hass.bus.listen(EVENT_PLATFORM_DISCOVERED, discovery_event_listener)
|
|
|
|
|
|
def discover(hass, service, discovered=None, component=None, hass_config=None):
|
|
"""Fire discovery event. Can ensure a component is loaded."""
|
|
if component is not None:
|
|
bootstrap.setup_component(hass, component, hass_config)
|
|
|
|
data = {
|
|
ATTR_SERVICE: service
|
|
}
|
|
|
|
if discovered is not None:
|
|
data[ATTR_DISCOVERED] = discovered
|
|
|
|
hass.bus.fire(EVENT_PLATFORM_DISCOVERED, data)
|
|
|
|
|
|
def listen_platform(hass, component, callback):
|
|
"""Register a platform loader listener."""
|
|
run_callback_threadsafe(
|
|
hass.loop, async_listen_platform, hass, component, callback
|
|
).result()
|
|
|
|
|
|
def async_listen_platform(hass, component, callback):
|
|
"""Register a platform loader listener.
|
|
|
|
This method must be run in the event loop.
|
|
"""
|
|
service = EVENT_LOAD_PLATFORM.format(component)
|
|
|
|
@core.callback
|
|
def discovery_platform_listener(event):
|
|
"""Listen for platform discovery events."""
|
|
if event.data.get(ATTR_SERVICE) != service:
|
|
return
|
|
|
|
platform = event.data.get(ATTR_PLATFORM)
|
|
|
|
if not platform:
|
|
return
|
|
|
|
hass.async_run_job(
|
|
callback, platform, event.data.get(ATTR_DISCOVERED)
|
|
)
|
|
|
|
hass.bus.async_listen(
|
|
EVENT_PLATFORM_DISCOVERED, discovery_platform_listener)
|
|
|
|
|
|
def load_platform(hass, component, platform, discovered=None,
|
|
hass_config=None):
|
|
"""Load a component and platform dynamically.
|
|
|
|
Target components will be loaded and an EVENT_PLATFORM_DISCOVERED will be
|
|
fired to load the platform. The event will contain:
|
|
{ ATTR_SERVICE = LOAD_PLATFORM + '.' + <<component>>
|
|
ATTR_PLATFORM = <<platform>>
|
|
ATTR_DISCOVERED = <<discovery info>> }
|
|
|
|
Use `listen_platform` to register a callback for these events.
|
|
"""
|
|
def discover_platform():
|
|
"""Discover platform job."""
|
|
# No need to fire event if we could not setup component
|
|
if not bootstrap.setup_component(hass, component, hass_config):
|
|
return
|
|
|
|
data = {
|
|
ATTR_SERVICE: EVENT_LOAD_PLATFORM.format(component),
|
|
ATTR_PLATFORM: platform,
|
|
}
|
|
|
|
if discovered is not None:
|
|
data[ATTR_DISCOVERED] = discovered
|
|
|
|
hass.bus.fire(EVENT_PLATFORM_DISCOVERED, data)
|
|
|
|
hass.add_job(discover_platform)
|