Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 40 additions & 51 deletions homeassistant/components/automation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,38 +158,36 @@ def async_reload(hass):
return hass.services.async_call(DOMAIN, SERVICE_RELOAD)


@asyncio.coroutine
def async_setup(hass, config):
async def async_setup(hass, config):
"""Set up the automation."""
component = EntityComponent(_LOGGER, DOMAIN, hass,
group_name=GROUP_NAME_ALL_AUTOMATIONS)

yield from _async_process_config(hass, config, component)
await _async_process_config(hass, config, component)

@asyncio.coroutine
def trigger_service_handler(service_call):
async def trigger_service_handler(service_call):
"""Handle automation triggers."""
tasks = []
for entity in component.async_extract_from_service(service_call):
tasks.append(entity.async_trigger(
service_call.data.get(ATTR_VARIABLES), True))
service_call.data.get(ATTR_VARIABLES),
skip_condition=True,
context=service_call.context))

if tasks:
yield from asyncio.wait(tasks, loop=hass.loop)
await asyncio.wait(tasks, loop=hass.loop)

@asyncio.coroutine
def turn_onoff_service_handler(service_call):
async def turn_onoff_service_handler(service_call):
"""Handle automation turn on/off service calls."""
tasks = []
method = 'async_{}'.format(service_call.service)
for entity in component.async_extract_from_service(service_call):
tasks.append(getattr(entity, method)())

if tasks:
yield from asyncio.wait(tasks, loop=hass.loop)
await asyncio.wait(tasks, loop=hass.loop)

@asyncio.coroutine
def toggle_service_handler(service_call):
async def toggle_service_handler(service_call):
"""Handle automation toggle service calls."""
tasks = []
for entity in component.async_extract_from_service(service_call):
Expand All @@ -199,15 +197,14 @@ def toggle_service_handler(service_call):
tasks.append(entity.async_turn_on())

if tasks:
yield from asyncio.wait(tasks, loop=hass.loop)
await asyncio.wait(tasks, loop=hass.loop)

@asyncio.coroutine
def reload_service_handler(service_call):
async def reload_service_handler(service_call):
"""Remove all automations and load new ones from config."""
conf = yield from component.async_prepare_reload()
conf = await component.async_prepare_reload()
if conf is None:
return
yield from _async_process_config(hass, conf, component)
await _async_process_config(hass, conf, component)

hass.services.async_register(
DOMAIN, SERVICE_TRIGGER, trigger_service_handler,
Expand Down Expand Up @@ -272,15 +269,14 @@ def is_on(self) -> bool:
"""Return True if entity is on."""
return self._async_detach_triggers is not None

@asyncio.coroutine
def async_added_to_hass(self) -> None:
async def async_added_to_hass(self) -> None:
"""Startup with initial state or previous state."""
if self._initial_state is not None:
enable_automation = self._initial_state
_LOGGER.debug("Automation %s initial state %s from config "
"initial_state", self.entity_id, enable_automation)
else:
state = yield from async_get_last_state(self.hass, self.entity_id)
state = await async_get_last_state(self.hass, self.entity_id)
if state:
enable_automation = state.state == STATE_ON
self._last_triggered = state.attributes.get('last_triggered')
Expand All @@ -298,64 +294,60 @@ def async_added_to_hass(self) -> None:

# HomeAssistant is starting up
if self.hass.state == CoreState.not_running:
@asyncio.coroutine
def async_enable_automation(event):
async def async_enable_automation(event):
"""Start automation on startup."""
yield from self.async_enable()
await self.async_enable()

self.hass.bus.async_listen_once(
EVENT_HOMEASSISTANT_START, async_enable_automation)

# HomeAssistant is running
else:
yield from self.async_enable()
await self.async_enable()

@asyncio.coroutine
def async_turn_on(self, **kwargs) -> None:
async def async_turn_on(self, **kwargs) -> None:
"""Turn the entity on and update the state."""
if self.is_on:
return

yield from self.async_enable()
await self.async_enable()

@asyncio.coroutine
def async_turn_off(self, **kwargs) -> None:
async def async_turn_off(self, **kwargs) -> None:
"""Turn the entity off."""
if not self.is_on:
return

self._async_detach_triggers()
self._async_detach_triggers = None
yield from self.async_update_ha_state()
await self.async_update_ha_state()

@asyncio.coroutine
def async_trigger(self, variables, skip_condition=False):
async def async_trigger(self, variables, skip_condition=False,
context=None):
"""Trigger automation.

This method is a coroutine.
"""
if skip_condition or self._cond_func(variables):
yield from self._async_action(self.entity_id, variables)
self.async_set_context(context)
await self._async_action(self.entity_id, variables, context)
self._last_triggered = utcnow()
yield from self.async_update_ha_state()
await self.async_update_ha_state()

@asyncio.coroutine
def async_will_remove_from_hass(self):
async def async_will_remove_from_hass(self):
"""Remove listeners when removing automation from HASS."""
yield from self.async_turn_off()
await self.async_turn_off()

@asyncio.coroutine
def async_enable(self):
async def async_enable(self):
"""Enable this automation entity.

This method is a coroutine.
"""
if self.is_on:
return

self._async_detach_triggers = yield from self._async_attach_triggers(
self._async_detach_triggers = await self._async_attach_triggers(
self.async_trigger)
yield from self.async_update_ha_state()
await self.async_update_ha_state()

@property
def device_state_attributes(self):
Expand All @@ -368,8 +360,7 @@ def device_state_attributes(self):
}


@asyncio.coroutine
def _async_process_config(hass, config, component):
async def _async_process_config(hass, config, component):
"""Process config and add automations.

This method is a coroutine.
Expand Down Expand Up @@ -411,20 +402,19 @@ def cond_func(variables):
entities.append(entity)

if entities:
yield from component.async_add_entities(entities)
await component.async_add_entities(entities)


def _async_get_action(hass, config, name):
"""Return an action based on a configuration."""
script_obj = script.Script(hass, config, name)

@asyncio.coroutine
def action(entity_id, variables):
async def action(entity_id, variables, context):
"""Execute an action."""
_LOGGER.info('Executing %s', name)
logbook.async_log_entry(
hass, name, 'has been triggered', DOMAIN, entity_id)
yield from script_obj.async_run(variables)
await script_obj.async_run(variables, context)

return action

Expand All @@ -448,22 +438,21 @@ def if_action(variables=None):
return if_action


@asyncio.coroutine
def _async_process_trigger(hass, config, trigger_configs, name, action):
async def _async_process_trigger(hass, config, trigger_configs, name, action):
"""Set up the triggers.

This method is a coroutine.
"""
removes = []

for conf in trigger_configs:
platform = yield from async_prepare_setup_platform(
platform = await async_prepare_setup_platform(
hass, config, DOMAIN, conf.get(CONF_PLATFORM))

if platform is None:
return None

remove = yield from platform.async_trigger(hass, conf, action)
remove = await platform.async_trigger(hass, conf, action)

if not remove:
_LOGGER.error("Error setting up trigger %s", name)
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/automation/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ def handle_event(event):
# If event data doesn't match requested schema, skip event
return

hass.async_run_job(action, {
hass.async_run_job(action({
'trigger': {
'platform': 'event',
'event': event,
},
})
}, context=event.context))

return hass.bus.async_listen(event_type, handle_event)
8 changes: 4 additions & 4 deletions homeassistant/components/automation/homeassistant.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,24 +32,24 @@ def async_trigger(hass, config, action):
@callback
def hass_shutdown(event):
"""Execute when Home Assistant is shutting down."""
hass.async_run_job(action, {
hass.async_run_job(action({
'trigger': {
'platform': 'homeassistant',
'event': event,
},
})
}, context=event.context))

return hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP,
hass_shutdown)

# Automation are enabled while hass is starting up, fire right away
# Check state because a config reload shouldn't trigger it.
if hass.state == CoreState.starting:
hass.async_run_job(action, {
hass.async_run_job(action({
'trigger': {
'platform': 'homeassistant',
'event': event,
},
})
}))

return lambda: None
4 changes: 2 additions & 2 deletions homeassistant/components/automation/numeric_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def state_automation_listener(entity, from_s, to_s):
@callback
def call_action():
"""Call action with right context."""
hass.async_run_job(action, {
hass.async_run_job(action({
'trigger': {
'platform': 'numeric_state',
'entity_id': entity,
Expand All @@ -75,7 +75,7 @@ def call_action():
'from_state': from_s,
'to_state': to_s,
}
})
}, context=to_s.context))

matching = check_numeric_state(entity, from_s, to_s)

Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/automation/state.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,15 @@ def state_automation_listener(entity, from_s, to_s):
@callback
def call_action():
"""Call action with right context."""
hass.async_run_job(action, {
hass.async_run_job(action({
'trigger': {
'platform': 'state',
'entity_id': entity,
'from_state': from_s,
'to_state': to_s,
'for': time_delta,
}
})
}, context=to_s.context))

# Ignore changes to state attributes if from/to is in use
if (not match_all and from_s is not None and to_s is not None and
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/automation/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ def async_trigger(hass, config, action):
@callback
def template_listener(entity_id, from_s, to_s):
"""Listen for state changes and calls action."""
hass.async_run_job(action, {
hass.async_run_job(action({
'trigger': {
'platform': 'template',
'entity_id': entity_id,
'from_state': from_s,
'to_state': to_s,
},
})
}, context=to_s.context))

return async_track_template(hass, value_template, template_listener)
4 changes: 2 additions & 2 deletions homeassistant/components/automation/zone.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def zone_automation_listener(entity, from_s, to_s):
# pylint: disable=too-many-boolean-expressions
if event == EVENT_ENTER and not from_match and to_match or \
event == EVENT_LEAVE and from_match and not to_match:
hass.async_run_job(action, {
hass.async_run_job(action({
'trigger': {
'platform': 'zone',
'entity_id': entity,
Expand All @@ -60,7 +60,7 @@ def zone_automation_listener(entity, from_s, to_s):
'zone': zone_state,
'event': event,
},
})
}, context=to_s.context))

return async_track_state_change(hass, entity_id, zone_automation_listener,
MATCH_ALL, MATCH_ALL)
Loading