mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 17:57:55 +00:00
Add unique IDs to automation/scenes (#31150)
* Add unique IDs to automation and scenes * Fix typo
This commit is contained in:
parent
8fff6462a1
commit
1f0f62de7f
@ -189,6 +189,11 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
|
|||||||
"""Name of the automation."""
|
"""Name of the automation."""
|
||||||
return self._name
|
return self._name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_id(self):
|
||||||
|
"""Return unique ID."""
|
||||||
|
return self._id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def should_poll(self):
|
def should_poll(self):
|
||||||
"""No polling needed for automation entities."""
|
"""No polling needed for automation entities."""
|
||||||
|
@ -28,6 +28,8 @@ SECTIONS = (
|
|||||||
"scene",
|
"scene",
|
||||||
)
|
)
|
||||||
ON_DEMAND = ("zwave",)
|
ON_DEMAND = ("zwave",)
|
||||||
|
ACTION_CREATE_UPDATE = "create_update"
|
||||||
|
ACTION_DELETE = "delete"
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass, config):
|
async def async_setup(hass, config):
|
||||||
@ -152,7 +154,9 @@ class BaseEditConfigView(HomeAssistantView):
|
|||||||
await hass.async_add_executor_job(_write, path, current)
|
await hass.async_add_executor_job(_write, path, current)
|
||||||
|
|
||||||
if self.post_write_hook is not None:
|
if self.post_write_hook is not None:
|
||||||
hass.async_create_task(self.post_write_hook(hass))
|
hass.async_create_task(
|
||||||
|
self.post_write_hook(ACTION_CREATE_UPDATE, config_key)
|
||||||
|
)
|
||||||
|
|
||||||
return self.json({"result": "ok"})
|
return self.json({"result": "ok"})
|
||||||
|
|
||||||
@ -170,7 +174,7 @@ class BaseEditConfigView(HomeAssistantView):
|
|||||||
await hass.async_add_executor_job(_write, path, current)
|
await hass.async_add_executor_job(_write, path, current)
|
||||||
|
|
||||||
if self.post_write_hook is not None:
|
if self.post_write_hook is not None:
|
||||||
hass.async_create_task(self.post_write_hook(hass))
|
hass.async_create_task(self.post_write_hook(ACTION_DELETE, config_key))
|
||||||
|
|
||||||
return self.json({"result": "ok"})
|
return self.json({"result": "ok"})
|
||||||
|
|
||||||
|
@ -6,18 +6,30 @@ from homeassistant.components.automation import DOMAIN, PLATFORM_SCHEMA
|
|||||||
from homeassistant.components.automation.config import async_validate_config_item
|
from homeassistant.components.automation.config import async_validate_config_item
|
||||||
from homeassistant.config import AUTOMATION_CONFIG_PATH
|
from homeassistant.config import AUTOMATION_CONFIG_PATH
|
||||||
from homeassistant.const import CONF_ID, SERVICE_RELOAD
|
from homeassistant.const import CONF_ID, SERVICE_RELOAD
|
||||||
import homeassistant.helpers.config_validation as cv
|
from homeassistant.helpers import config_validation as cv, entity_registry
|
||||||
|
|
||||||
from . import EditIdBasedConfigView
|
from . import ACTION_DELETE, EditIdBasedConfigView
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass):
|
async def async_setup(hass):
|
||||||
"""Set up the Automation config API."""
|
"""Set up the Automation config API."""
|
||||||
|
|
||||||
async def hook(hass):
|
async def hook(action, config_key):
|
||||||
"""post_write_hook for Config View that reloads automations."""
|
"""post_write_hook for Config View that reloads automations."""
|
||||||
await hass.services.async_call(DOMAIN, SERVICE_RELOAD)
|
await hass.services.async_call(DOMAIN, SERVICE_RELOAD)
|
||||||
|
|
||||||
|
if action != ACTION_DELETE:
|
||||||
|
return
|
||||||
|
|
||||||
|
ent_reg = await entity_registry.async_get_registry(hass)
|
||||||
|
|
||||||
|
entity_id = ent_reg.async_get_entity_id(DOMAIN, DOMAIN, config_key)
|
||||||
|
|
||||||
|
if entity_id is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
ent_reg.async_remove(entity_id)
|
||||||
|
|
||||||
hass.http.register_view(
|
hass.http.register_view(
|
||||||
EditAutomationConfigView(
|
EditAutomationConfigView(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
@ -12,7 +12,7 @@ CONFIG_PATH = "customize.yaml"
|
|||||||
async def async_setup(hass):
|
async def async_setup(hass):
|
||||||
"""Set up the Customize config API."""
|
"""Set up the Customize config API."""
|
||||||
|
|
||||||
async def hook(hass):
|
async def hook(action, config_key):
|
||||||
"""post_write_hook for Config View that reloads groups."""
|
"""post_write_hook for Config View that reloads groups."""
|
||||||
await hass.services.async_call(DOMAIN, SERVICE_RELOAD_CORE_CONFIG)
|
await hass.services.async_call(DOMAIN, SERVICE_RELOAD_CORE_CONFIG)
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ from . import EditKeyBasedConfigView
|
|||||||
async def async_setup(hass):
|
async def async_setup(hass):
|
||||||
"""Set up the Group config API."""
|
"""Set up the Group config API."""
|
||||||
|
|
||||||
async def hook(hass):
|
async def hook(action, config_key):
|
||||||
"""post_write_hook for Config View that reloads groups."""
|
"""post_write_hook for Config View that reloads groups."""
|
||||||
await hass.services.async_call(DOMAIN, SERVICE_RELOAD)
|
await hass.services.async_call(DOMAIN, SERVICE_RELOAD)
|
||||||
|
|
||||||
|
@ -5,18 +5,31 @@ import uuid
|
|||||||
from homeassistant.components.scene import DOMAIN, PLATFORM_SCHEMA
|
from homeassistant.components.scene import DOMAIN, PLATFORM_SCHEMA
|
||||||
from homeassistant.config import SCENE_CONFIG_PATH
|
from homeassistant.config import SCENE_CONFIG_PATH
|
||||||
from homeassistant.const import CONF_ID, SERVICE_RELOAD
|
from homeassistant.const import CONF_ID, SERVICE_RELOAD
|
||||||
import homeassistant.helpers.config_validation as cv
|
from homeassistant.core import DOMAIN as HA_DOMAIN
|
||||||
|
from homeassistant.helpers import config_validation as cv, entity_registry
|
||||||
|
|
||||||
from . import EditIdBasedConfigView
|
from . import ACTION_DELETE, EditIdBasedConfigView
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass):
|
async def async_setup(hass):
|
||||||
"""Set up the Scene config API."""
|
"""Set up the Scene config API."""
|
||||||
|
|
||||||
async def hook(hass):
|
async def hook(action, config_key):
|
||||||
"""post_write_hook for Config View that reloads scenes."""
|
"""post_write_hook for Config View that reloads scenes."""
|
||||||
await hass.services.async_call(DOMAIN, SERVICE_RELOAD)
|
await hass.services.async_call(DOMAIN, SERVICE_RELOAD)
|
||||||
|
|
||||||
|
if action != ACTION_DELETE:
|
||||||
|
return
|
||||||
|
|
||||||
|
ent_reg = await entity_registry.async_get_registry(hass)
|
||||||
|
|
||||||
|
entity_id = ent_reg.async_get_entity_id(DOMAIN, HA_DOMAIN, config_key)
|
||||||
|
|
||||||
|
if entity_id is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
ent_reg.async_remove(entity_id)
|
||||||
|
|
||||||
hass.http.register_view(
|
hass.http.register_view(
|
||||||
EditSceneConfigView(
|
EditSceneConfigView(
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
@ -10,7 +10,7 @@ from . import EditKeyBasedConfigView
|
|||||||
async def async_setup(hass):
|
async def async_setup(hass):
|
||||||
"""Set up the script config API."""
|
"""Set up the script config API."""
|
||||||
|
|
||||||
async def hook(hass):
|
async def hook(action, config_key):
|
||||||
"""post_write_hook for Config View that reloads scripts."""
|
"""post_write_hook for Config View that reloads scripts."""
|
||||||
await hass.services.async_call(DOMAIN, SERVICE_RELOAD)
|
await hass.services.async_call(DOMAIN, SERVICE_RELOAD)
|
||||||
|
|
||||||
|
@ -261,6 +261,11 @@ class HomeAssistantScene(Scene):
|
|||||||
"""Return the name of the scene."""
|
"""Return the name of the scene."""
|
||||||
return self.scene_config.name
|
return self.scene_config.name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_id(self):
|
||||||
|
"""Return unique ID."""
|
||||||
|
return self._id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_state_attributes(self):
|
def device_state_attributes(self):
|
||||||
"""Return the scene state attributes."""
|
"""Return the scene state attributes."""
|
||||||
|
@ -61,10 +61,7 @@ async def async_setup(hass, config):
|
|||||||
|
|
||||||
await component.async_setup(config)
|
await component.async_setup(config)
|
||||||
# Ensure Home Assistant platform always loaded.
|
# Ensure Home Assistant platform always loaded.
|
||||||
await component.async_setup_platform(
|
await component.async_setup_platform(HA_DOMAIN, {"platform": HA_DOMAIN, STATES: []})
|
||||||
HA_DOMAIN, {"platform": "homeasistant", STATES: []}
|
|
||||||
)
|
|
||||||
|
|
||||||
component.async_register_entity_service(SERVICE_TURN_ON, {}, "async_activate")
|
component.async_register_entity_service(SERVICE_TURN_ON, {}, "async_activate")
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
"""Test Automation config panel."""
|
"""Test Automation config panel."""
|
||||||
import json
|
import json
|
||||||
from unittest.mock import patch
|
|
||||||
|
from asynctest import patch
|
||||||
|
|
||||||
from homeassistant.bootstrap import async_setup_component
|
from homeassistant.bootstrap import async_setup_component
|
||||||
from homeassistant.components import config
|
from homeassistant.components import config
|
||||||
@ -47,7 +48,7 @@ async def test_update_device_config(hass, hass_client):
|
|||||||
|
|
||||||
with patch("homeassistant.components.config._read", mock_read), patch(
|
with patch("homeassistant.components.config._read", mock_read), patch(
|
||||||
"homeassistant.components.config._write", mock_write
|
"homeassistant.components.config._write", mock_write
|
||||||
):
|
), patch("homeassistant.config.async_hass_config_yaml", return_value={}):
|
||||||
resp = await client.post(
|
resp = await client.post(
|
||||||
"/api/config/automation/config/moon",
|
"/api/config/automation/config/moon",
|
||||||
data=json.dumps({"trigger": [], "action": [], "condition": []}),
|
data=json.dumps({"trigger": [], "action": [], "condition": []}),
|
||||||
@ -89,11 +90,12 @@ async def test_bad_formatted_automations(hass, hass_client):
|
|||||||
|
|
||||||
with patch("homeassistant.components.config._read", mock_read), patch(
|
with patch("homeassistant.components.config._read", mock_read), patch(
|
||||||
"homeassistant.components.config._write", mock_write
|
"homeassistant.components.config._write", mock_write
|
||||||
):
|
), patch("homeassistant.config.async_hass_config_yaml", return_value={}):
|
||||||
resp = await client.post(
|
resp = await client.post(
|
||||||
"/api/config/automation/config/moon",
|
"/api/config/automation/config/moon",
|
||||||
data=json.dumps({"trigger": [], "action": [], "condition": []}),
|
data=json.dumps({"trigger": [], "action": [], "condition": []}),
|
||||||
)
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
result = await resp.json()
|
result = await resp.json()
|
||||||
@ -107,8 +109,31 @@ async def test_bad_formatted_automations(hass, hass_client):
|
|||||||
|
|
||||||
async def test_delete_automation(hass, hass_client):
|
async def test_delete_automation(hass, hass_client):
|
||||||
"""Test deleting an automation."""
|
"""Test deleting an automation."""
|
||||||
|
ent_reg = await hass.helpers.entity_registry.async_get_registry()
|
||||||
|
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
"automation",
|
||||||
|
{
|
||||||
|
"automation": [
|
||||||
|
{
|
||||||
|
"id": "sun",
|
||||||
|
"trigger": {"platform": "event", "event_type": "test_event"},
|
||||||
|
"action": {"service": "test.automation"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "moon",
|
||||||
|
"trigger": {"platform": "event", "event_type": "test_event"},
|
||||||
|
"action": {"service": "test.automation"},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(ent_reg.entities) == 2
|
||||||
|
|
||||||
with patch.object(config, "SECTIONS", ["automation"]):
|
with patch.object(config, "SECTIONS", ["automation"]):
|
||||||
await async_setup_component(hass, "config", {})
|
assert await async_setup_component(hass, "config", {})
|
||||||
|
|
||||||
client = await hass_client()
|
client = await hass_client()
|
||||||
|
|
||||||
@ -126,8 +151,9 @@ async def test_delete_automation(hass, hass_client):
|
|||||||
|
|
||||||
with patch("homeassistant.components.config._read", mock_read), patch(
|
with patch("homeassistant.components.config._read", mock_read), patch(
|
||||||
"homeassistant.components.config._write", mock_write
|
"homeassistant.components.config._write", mock_write
|
||||||
):
|
), patch("homeassistant.config.async_hass_config_yaml", return_value={}):
|
||||||
resp = await client.delete("/api/config/automation/config/sun")
|
resp = await client.delete("/api/config/automation/config/sun")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
result = await resp.json()
|
result = await resp.json()
|
||||||
@ -135,3 +161,5 @@ async def test_delete_automation(hass, hass_client):
|
|||||||
|
|
||||||
assert len(written) == 1
|
assert len(written) == 1
|
||||||
assert written[0][0]["id"] == "moon"
|
assert written[0][0]["id"] == "moon"
|
||||||
|
|
||||||
|
assert len(ent_reg.entities) == 1
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
"""Test Customize config panel."""
|
"""Test Customize config panel."""
|
||||||
import json
|
import json
|
||||||
from unittest.mock import patch
|
|
||||||
|
from asynctest import patch
|
||||||
|
|
||||||
from homeassistant.bootstrap import async_setup_component
|
from homeassistant.bootstrap import async_setup_component
|
||||||
from homeassistant.components import config
|
from homeassistant.components import config
|
||||||
@ -53,6 +54,8 @@ async def test_update_entity(hass, hass_client):
|
|||||||
hass.states.async_set("hello.world", "state", {"a": "b"})
|
hass.states.async_set("hello.world", "state", {"a": "b"})
|
||||||
with patch("homeassistant.components.config._read", mock_read), patch(
|
with patch("homeassistant.components.config._read", mock_read), patch(
|
||||||
"homeassistant.components.config._write", mock_write
|
"homeassistant.components.config._write", mock_write
|
||||||
|
), patch(
|
||||||
|
"homeassistant.config.async_hass_config_yaml", return_value={},
|
||||||
):
|
):
|
||||||
resp = await client.post(
|
resp = await client.post(
|
||||||
"/api/config/customize/config/hello.world",
|
"/api/config/customize/config/hello.world",
|
||||||
@ -60,6 +63,7 @@ async def test_update_entity(hass, hass_client):
|
|||||||
{"name": "Beer", "entities": ["light.top", "light.bottom"]}
|
{"name": "Beer", "entities": ["light.top", "light.bottom"]}
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
result = await resp.json()
|
result = await resp.json()
|
||||||
|
@ -61,6 +61,7 @@ async def test_update_device_config(hass, hass_client):
|
|||||||
{"name": "Beer", "entities": ["light.top", "light.bottom"]}
|
{"name": "Beer", "entities": ["light.top", "light.bottom"]}
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
result = await resp.json()
|
result = await resp.json()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
"""Test Automation config panel."""
|
"""Test Automation config panel."""
|
||||||
import json
|
import json
|
||||||
from unittest.mock import patch
|
|
||||||
|
from asynctest import patch
|
||||||
|
|
||||||
from homeassistant.bootstrap import async_setup_component
|
from homeassistant.bootstrap import async_setup_component
|
||||||
from homeassistant.components import config
|
from homeassistant.components import config
|
||||||
@ -29,7 +30,7 @@ async def test_update_scene(hass, hass_client):
|
|||||||
|
|
||||||
with patch("homeassistant.components.config._read", mock_read), patch(
|
with patch("homeassistant.components.config._read", mock_read), patch(
|
||||||
"homeassistant.components.config._write", mock_write
|
"homeassistant.components.config._write", mock_write
|
||||||
):
|
), patch("homeassistant.config.async_hass_config_yaml", return_value={}):
|
||||||
resp = await client.post(
|
resp = await client.post(
|
||||||
"/api/config/scene/config/light_off",
|
"/api/config/scene/config/light_off",
|
||||||
data=json.dumps(
|
data=json.dumps(
|
||||||
@ -86,7 +87,7 @@ async def test_bad_formatted_scene(hass, hass_client):
|
|||||||
|
|
||||||
with patch("homeassistant.components.config._read", mock_read), patch(
|
with patch("homeassistant.components.config._read", mock_read), patch(
|
||||||
"homeassistant.components.config._write", mock_write
|
"homeassistant.components.config._write", mock_write
|
||||||
):
|
), patch("homeassistant.config.async_hass_config_yaml", return_value={}):
|
||||||
resp = await client.post(
|
resp = await client.post(
|
||||||
"/api/config/scene/config/light_off",
|
"/api/config/scene/config/light_off",
|
||||||
data=json.dumps(
|
data=json.dumps(
|
||||||
@ -114,8 +115,23 @@ async def test_bad_formatted_scene(hass, hass_client):
|
|||||||
|
|
||||||
async def test_delete_scene(hass, hass_client):
|
async def test_delete_scene(hass, hass_client):
|
||||||
"""Test deleting a scene."""
|
"""Test deleting a scene."""
|
||||||
|
ent_reg = await hass.helpers.entity_registry.async_get_registry()
|
||||||
|
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
"scene",
|
||||||
|
{
|
||||||
|
"scene": [
|
||||||
|
{"id": "light_on", "name": "Light on", "entities": {}},
|
||||||
|
{"id": "light_off", "name": "Light off", "entities": {}},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(ent_reg.entities) == 2
|
||||||
|
|
||||||
with patch.object(config, "SECTIONS", ["scene"]):
|
with patch.object(config, "SECTIONS", ["scene"]):
|
||||||
await async_setup_component(hass, "config", {})
|
assert await async_setup_component(hass, "config", {})
|
||||||
|
|
||||||
client = await hass_client()
|
client = await hass_client()
|
||||||
|
|
||||||
@ -133,8 +149,9 @@ async def test_delete_scene(hass, hass_client):
|
|||||||
|
|
||||||
with patch("homeassistant.components.config._read", mock_read), patch(
|
with patch("homeassistant.components.config._read", mock_read), patch(
|
||||||
"homeassistant.components.config._write", mock_write
|
"homeassistant.components.config._write", mock_write
|
||||||
):
|
), patch("homeassistant.config.async_hass_config_yaml", return_value={}):
|
||||||
resp = await client.delete("/api/config/scene/config/light_on")
|
resp = await client.delete("/api/config/scene/config/light_on")
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert resp.status == 200
|
assert resp.status == 200
|
||||||
result = await resp.json()
|
result = await resp.json()
|
||||||
@ -142,3 +159,5 @@ async def test_delete_scene(hass, hass_client):
|
|||||||
|
|
||||||
assert len(written) == 1
|
assert len(written) == 1
|
||||||
assert written[0][0]["id"] == "light_off"
|
assert written[0][0]["id"] == "light_off"
|
||||||
|
|
||||||
|
assert len(ent_reg.entities) == 1
|
||||||
|
@ -3,7 +3,7 @@ import io
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from homeassistant.components import light, scene
|
from homeassistant.components import light, scene
|
||||||
from homeassistant.setup import setup_component
|
from homeassistant.setup import async_setup_component, setup_component
|
||||||
from homeassistant.util.yaml import loader as yaml_loader
|
from homeassistant.util.yaml import loader as yaml_loader
|
||||||
|
|
||||||
from tests.common import get_test_home_assistant
|
from tests.common import get_test_home_assistant
|
||||||
@ -128,3 +128,11 @@ class TestScene(unittest.TestCase):
|
|||||||
assert self.light_1.is_on
|
assert self.light_1.is_on
|
||||||
assert self.light_2.is_on
|
assert self.light_2.is_on
|
||||||
assert 100 == self.light_2.last_call("turn_on")[1].get("brightness")
|
assert 100 == self.light_2.last_call("turn_on")[1].get("brightness")
|
||||||
|
|
||||||
|
|
||||||
|
async def test_services_registered(hass):
|
||||||
|
"""Test we register services with empty config."""
|
||||||
|
assert await async_setup_component(hass, "scene", {})
|
||||||
|
assert hass.services.has_service("scene", "reload")
|
||||||
|
assert hass.services.has_service("scene", "turn_on")
|
||||||
|
assert hass.services.has_service("scene", "apply")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user