Convert script component to async (#4427)

This commit is contained in:
Paulus Schoutsen 2016-11-17 21:50:01 -08:00 committed by GitHub
parent 726bc5b670
commit 23fb8c4cdd
2 changed files with 42 additions and 21 deletions

View file

@ -7,6 +7,7 @@ by the user or automatically based upon automation events, etc.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
https://home-assistant.io/components/script/ https://home-assistant.io/components/script/
""" """
import asyncio
import logging import logging
import voluptuous as vol import voluptuous as vol
@ -72,11 +73,13 @@ def toggle(hass, entity_id):
hass.services.call(DOMAIN, SERVICE_TOGGLE, {ATTR_ENTITY_ID: entity_id}) hass.services.call(DOMAIN, SERVICE_TOGGLE, {ATTR_ENTITY_ID: entity_id})
def setup(hass, config): @asyncio.coroutine
def async_setup(hass, config):
"""Load the scripts from the configuration.""" """Load the scripts from the configuration."""
component = EntityComponent(_LOGGER, DOMAIN, hass, component = EntityComponent(_LOGGER, DOMAIN, hass,
group_name=GROUP_NAME_ALL_SCRIPTS) group_name=GROUP_NAME_ALL_SCRIPTS)
@asyncio.coroutine
def service_handler(service): def service_handler(service):
"""Execute a service call to script.<script name>.""" """Execute a service call to script.<script name>."""
entity_id = ENTITY_ID_FORMAT.format(service.service) entity_id = ENTITY_ID_FORMAT.format(service.service)
@ -84,38 +87,48 @@ def setup(hass, config):
if script.is_on: if script.is_on:
_LOGGER.warning("Script %s already running.", entity_id) _LOGGER.warning("Script %s already running.", entity_id)
return return
script.turn_on(variables=service.data) yield from script.async_turn_on(variables=service.data)
scripts = []
for object_id, cfg in config[DOMAIN].items(): for object_id, cfg in config[DOMAIN].items():
alias = cfg.get(CONF_ALIAS, object_id) alias = cfg.get(CONF_ALIAS, object_id)
script = ScriptEntity(hass, object_id, alias, cfg[CONF_SEQUENCE]) script = ScriptEntity(hass, object_id, alias, cfg[CONF_SEQUENCE])
component.add_entities((script,)) scripts.append(script)
hass.services.register(DOMAIN, object_id, service_handler, hass.services.async_register(DOMAIN, object_id, service_handler,
schema=SCRIPT_SERVICE_SCHEMA) schema=SCRIPT_SERVICE_SCHEMA)
yield from component.async_add_entities(scripts)
@asyncio.coroutine
def turn_on_service(service): def turn_on_service(service):
"""Call a service to turn script on.""" """Call a service to turn script on."""
# We could turn on script directly here, but we only want to offer # We could turn on script directly here, but we only want to offer
# one way to do it. Otherwise no easy way to detect invocations. # one way to do it. Otherwise no easy way to detect invocations.
for script in component.extract_from_service(service): var = service.data.get(ATTR_VARIABLES)
turn_on(hass, script.entity_id, service.data.get(ATTR_VARIABLES)) for script in component.async_extract_from_service(service):
yield from hass.services.async_call(DOMAIN, script.object_id, var)
@asyncio.coroutine
def turn_off_service(service): def turn_off_service(service):
"""Cancel a script.""" """Cancel a script."""
for script in component.extract_from_service(service): # Stopping a script is ok to be done in parallel
script.turn_off() yield from asyncio.wait(
[script.async_turn_off() for script
in component.async_extract_from_service(service)], loop=hass.loop)
@asyncio.coroutine
def toggle_service(service): def toggle_service(service):
"""Toggle a script.""" """Toggle a script."""
for script in component.extract_from_service(service): for script in component.async_extract_from_service(service):
script.toggle() yield from script.async_toggle()
hass.services.register(DOMAIN, SERVICE_TURN_ON, turn_on_service, hass.services.async_register(DOMAIN, SERVICE_TURN_ON, turn_on_service,
schema=SCRIPT_TURN_ONOFF_SCHEMA) schema=SCRIPT_TURN_ONOFF_SCHEMA)
hass.services.register(DOMAIN, SERVICE_TURN_OFF, turn_off_service, hass.services.async_register(DOMAIN, SERVICE_TURN_OFF, turn_off_service,
schema=SCRIPT_TURN_ONOFF_SCHEMA) schema=SCRIPT_TURN_ONOFF_SCHEMA)
hass.services.register(DOMAIN, SERVICE_TOGGLE, toggle_service, hass.services.async_register(DOMAIN, SERVICE_TOGGLE, toggle_service,
schema=SCRIPT_TURN_ONOFF_SCHEMA) schema=SCRIPT_TURN_ONOFF_SCHEMA)
return True return True
@ -124,6 +137,7 @@ class ScriptEntity(ToggleEntity):
def __init__(self, hass, object_id, name, sequence): def __init__(self, hass, object_id, name, sequence):
"""Initialize the script.""" """Initialize the script."""
self.object_id = object_id
self.entity_id = ENTITY_ID_FORMAT.format(object_id) self.entity_id = ENTITY_ID_FORMAT.format(object_id)
self.script = Script(hass, sequence, name, self.async_update_ha_state) self.script = Script(hass, sequence, name, self.async_update_ha_state)
@ -152,10 +166,12 @@ class ScriptEntity(ToggleEntity):
"""Return true if script is on.""" """Return true if script is on."""
return self.script.is_running return self.script.is_running
def turn_on(self, **kwargs): @asyncio.coroutine
def async_turn_on(self, **kwargs):
"""Turn the script on.""" """Turn the script on."""
self.script.run(kwargs.get(ATTR_VARIABLES)) yield from self.script.async_run(kwargs.get(ATTR_VARIABLES))
def turn_off(self, **kwargs): @asyncio.coroutine
def async_turn_off(self, **kwargs):
"""Turn script off.""" """Turn script off."""
self.script.stop() self.script.async_stop()

View file

@ -86,6 +86,11 @@ class TestScriptComponent(unittest.TestCase):
self.hass.block_till_done() self.hass.block_till_done()
self.assertEqual(0, len(events)) self.assertEqual(0, len(events))
script.turn_off(self.hass, ENTITY_ID)
self.hass.block_till_done()
self.assertFalse(script.is_on(self.hass, ENTITY_ID))
self.assertEqual(0, len(events))
state = self.hass.states.get('group.all_scripts') state = self.hass.states.get('group.all_scripts')
assert state is not None assert state is not None
assert state.attributes.get('entity_id') == (ENTITY_ID,) assert state.attributes.get('entity_id') == (ENTITY_ID,)