mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 04:37:06 +00:00
add script shortcut for activating scenes (#27223)
* add script shortcut for activating scenes use `- scene: scene.<scene name>` in a script to activate a scene * Update validation
This commit is contained in:
parent
43d1413050
commit
d16edb3ef0
@ -885,6 +885,8 @@ DEVICE_ACTION_BASE_SCHEMA = vol.Schema(
|
|||||||
|
|
||||||
DEVICE_ACTION_SCHEMA = DEVICE_ACTION_BASE_SCHEMA.extend({}, extra=vol.ALLOW_EXTRA)
|
DEVICE_ACTION_SCHEMA = DEVICE_ACTION_BASE_SCHEMA.extend({}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
|
_SCRIPT_SCENE_SCHEMA = vol.Schema({vol.Required("scene"): entity_domain("scene")})
|
||||||
|
|
||||||
SCRIPT_SCHEMA = vol.All(
|
SCRIPT_SCHEMA = vol.All(
|
||||||
ensure_list,
|
ensure_list,
|
||||||
[
|
[
|
||||||
@ -895,6 +897,7 @@ SCRIPT_SCHEMA = vol.All(
|
|||||||
EVENT_SCHEMA,
|
EVENT_SCHEMA,
|
||||||
CONDITION_SCHEMA,
|
CONDITION_SCHEMA,
|
||||||
DEVICE_ACTION_SCHEMA,
|
DEVICE_ACTION_SCHEMA,
|
||||||
|
_SCRIPT_SCENE_SCHEMA,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -9,12 +9,15 @@ from typing import Optional, Sequence, Callable, Dict, List, Set, Tuple, Any
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
import homeassistant.components.device_automation as device_automation
|
import homeassistant.components.device_automation as device_automation
|
||||||
|
import homeassistant.components.scene as scene
|
||||||
from homeassistant.core import HomeAssistant, Context, callback, CALLBACK_TYPE
|
from homeassistant.core import HomeAssistant, Context, callback, CALLBACK_TYPE
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
|
ATTR_ENTITY_ID,
|
||||||
CONF_CONDITION,
|
CONF_CONDITION,
|
||||||
CONF_DEVICE_ID,
|
CONF_DEVICE_ID,
|
||||||
CONF_DOMAIN,
|
CONF_DOMAIN,
|
||||||
CONF_TIMEOUT,
|
CONF_TIMEOUT,
|
||||||
|
SERVICE_TURN_ON,
|
||||||
)
|
)
|
||||||
from homeassistant import exceptions
|
from homeassistant import exceptions
|
||||||
from homeassistant.helpers import (
|
from homeassistant.helpers import (
|
||||||
@ -46,6 +49,7 @@ CONF_EVENT_DATA_TEMPLATE = "event_data_template"
|
|||||||
CONF_DELAY = "delay"
|
CONF_DELAY = "delay"
|
||||||
CONF_WAIT_TEMPLATE = "wait_template"
|
CONF_WAIT_TEMPLATE = "wait_template"
|
||||||
CONF_CONTINUE = "continue_on_timeout"
|
CONF_CONTINUE = "continue_on_timeout"
|
||||||
|
CONF_SCENE = "scene"
|
||||||
|
|
||||||
|
|
||||||
ACTION_DELAY = "delay"
|
ACTION_DELAY = "delay"
|
||||||
@ -54,6 +58,7 @@ ACTION_CHECK_CONDITION = "condition"
|
|||||||
ACTION_FIRE_EVENT = "event"
|
ACTION_FIRE_EVENT = "event"
|
||||||
ACTION_CALL_SERVICE = "call_service"
|
ACTION_CALL_SERVICE = "call_service"
|
||||||
ACTION_DEVICE_AUTOMATION = "device"
|
ACTION_DEVICE_AUTOMATION = "device"
|
||||||
|
ACTION_ACTIVATE_SCENE = "scene"
|
||||||
|
|
||||||
|
|
||||||
def _determine_action(action):
|
def _determine_action(action):
|
||||||
@ -73,6 +78,9 @@ def _determine_action(action):
|
|||||||
if CONF_DEVICE_ID in action:
|
if CONF_DEVICE_ID in action:
|
||||||
return ACTION_DEVICE_AUTOMATION
|
return ACTION_DEVICE_AUTOMATION
|
||||||
|
|
||||||
|
if CONF_SCENE in action:
|
||||||
|
return ACTION_ACTIVATE_SCENE
|
||||||
|
|
||||||
return ACTION_CALL_SERVICE
|
return ACTION_CALL_SERVICE
|
||||||
|
|
||||||
|
|
||||||
@ -147,6 +155,7 @@ class Script:
|
|||||||
ACTION_FIRE_EVENT: self._async_fire_event,
|
ACTION_FIRE_EVENT: self._async_fire_event,
|
||||||
ACTION_CALL_SERVICE: self._async_call_service,
|
ACTION_CALL_SERVICE: self._async_call_service,
|
||||||
ACTION_DEVICE_AUTOMATION: self._async_device_automation,
|
ACTION_DEVICE_AUTOMATION: self._async_device_automation,
|
||||||
|
ACTION_ACTIVATE_SCENE: self._async_activate_scene,
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -362,6 +371,21 @@ class Script:
|
|||||||
self.hass, action, variables, context
|
self.hass, action, variables, context
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async def _async_activate_scene(self, action, variables, context):
|
||||||
|
"""Activate the scene specified in the action.
|
||||||
|
|
||||||
|
This method is a coroutine.
|
||||||
|
"""
|
||||||
|
self.last_action = action.get(CONF_ALIAS, "activate scene")
|
||||||
|
self._log("Executing step %s" % self.last_action)
|
||||||
|
await self.hass.services.async_call(
|
||||||
|
scene.DOMAIN,
|
||||||
|
SERVICE_TURN_ON,
|
||||||
|
{ATTR_ENTITY_ID: action[CONF_SCENE]},
|
||||||
|
blocking=True,
|
||||||
|
context=context,
|
||||||
|
)
|
||||||
|
|
||||||
async def _async_fire_event(self, action, variables, context):
|
async def _async_fire_event(self, action, variables, context):
|
||||||
"""Fire an event."""
|
"""Fire an event."""
|
||||||
self.last_action = action.get(CONF_ALIAS, action[CONF_EVENT])
|
self.last_action = action.get(CONF_ALIAS, action[CONF_EVENT])
|
||||||
|
@ -9,7 +9,9 @@ import jinja2
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
import homeassistant.components.scene as scene
|
||||||
from homeassistant import exceptions
|
from homeassistant import exceptions
|
||||||
|
from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_ON
|
||||||
from homeassistant.core import Context, callback
|
from homeassistant.core import Context, callback
|
||||||
|
|
||||||
# Otherwise can't test just this file (import order issue)
|
# Otherwise can't test just this file (import order issue)
|
||||||
@ -120,6 +122,31 @@ async def test_calling_service(hass):
|
|||||||
assert calls[0].data.get("hello") == "world"
|
assert calls[0].data.get("hello") == "world"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_activating_scene(hass):
|
||||||
|
"""Test the activation of a scene."""
|
||||||
|
calls = []
|
||||||
|
context = Context()
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def record_call(service):
|
||||||
|
"""Add recorded event to set."""
|
||||||
|
calls.append(service)
|
||||||
|
|
||||||
|
hass.services.async_register(scene.DOMAIN, SERVICE_TURN_ON, record_call)
|
||||||
|
|
||||||
|
hass.async_add_job(
|
||||||
|
ft.partial(
|
||||||
|
script.call_from_config, hass, {"scene": "scene.hello"}, context=context
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(calls) == 1
|
||||||
|
assert calls[0].context is context
|
||||||
|
assert calls[0].data.get(ATTR_ENTITY_ID) == "scene.hello"
|
||||||
|
|
||||||
|
|
||||||
async def test_calling_service_template(hass):
|
async def test_calling_service_template(hass):
|
||||||
"""Test the calling of a service."""
|
"""Test the calling of a service."""
|
||||||
calls = []
|
calls = []
|
||||||
|
Loading…
x
Reference in New Issue
Block a user