Add unique IDs to automation/scenes (#31150)

* Add unique IDs to automation and scenes

* Fix typo
This commit is contained in:
Paulus Schoutsen 2020-01-26 23:01:35 -08:00 committed by GitHub
parent 8fff6462a1
commit 1f0f62de7f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 123 additions and 27 deletions

View file

@ -189,6 +189,11 @@ class AutomationEntity(ToggleEntity, RestoreEntity):
"""Name of the automation."""
return self._name
@property
def unique_id(self):
"""Return unique ID."""
return self._id
@property
def should_poll(self):
"""No polling needed for automation entities."""

View file

@ -28,6 +28,8 @@ SECTIONS = (
"scene",
)
ON_DEMAND = ("zwave",)
ACTION_CREATE_UPDATE = "create_update"
ACTION_DELETE = "delete"
async def async_setup(hass, config):
@ -152,7 +154,9 @@ class BaseEditConfigView(HomeAssistantView):
await hass.async_add_executor_job(_write, path, current)
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"})
@ -170,7 +174,7 @@ class BaseEditConfigView(HomeAssistantView):
await hass.async_add_executor_job(_write, path, current)
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"})

View file

@ -6,18 +6,30 @@ from homeassistant.components.automation import DOMAIN, PLATFORM_SCHEMA
from homeassistant.components.automation.config import async_validate_config_item
from homeassistant.config import AUTOMATION_CONFIG_PATH
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):
"""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."""
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(
EditAutomationConfigView(
DOMAIN,

View file

@ -12,7 +12,7 @@ CONFIG_PATH = "customize.yaml"
async def async_setup(hass):
"""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."""
await hass.services.async_call(DOMAIN, SERVICE_RELOAD_CORE_CONFIG)

View file

@ -10,7 +10,7 @@ from . import EditKeyBasedConfigView
async def async_setup(hass):
"""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."""
await hass.services.async_call(DOMAIN, SERVICE_RELOAD)

View file

@ -5,18 +5,31 @@ import uuid
from homeassistant.components.scene import DOMAIN, PLATFORM_SCHEMA
from homeassistant.config import SCENE_CONFIG_PATH
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):
"""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."""
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(
EditSceneConfigView(
DOMAIN,

View file

@ -10,7 +10,7 @@ from . import EditKeyBasedConfigView
async def async_setup(hass):
"""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."""
await hass.services.async_call(DOMAIN, SERVICE_RELOAD)

View file

@ -261,6 +261,11 @@ class HomeAssistantScene(Scene):
"""Return the name of the scene."""
return self.scene_config.name
@property
def unique_id(self):
"""Return unique ID."""
return self._id
@property
def device_state_attributes(self):
"""Return the scene state attributes."""

View file

@ -61,10 +61,7 @@ async def async_setup(hass, config):
await component.async_setup(config)
# Ensure Home Assistant platform always loaded.
await component.async_setup_platform(
HA_DOMAIN, {"platform": "homeasistant", STATES: []}
)
await component.async_setup_platform(HA_DOMAIN, {"platform": HA_DOMAIN, STATES: []})
component.async_register_entity_service(SERVICE_TURN_ON, {}, "async_activate")
return True

View file

@ -1,6 +1,7 @@
"""Test Automation config panel."""
import json
from unittest.mock import patch
from asynctest import patch
from homeassistant.bootstrap import async_setup_component
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(
"homeassistant.components.config._write", mock_write
):
), patch("homeassistant.config.async_hass_config_yaml", return_value={}):
resp = await client.post(
"/api/config/automation/config/moon",
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(
"homeassistant.components.config._write", mock_write
):
), patch("homeassistant.config.async_hass_config_yaml", return_value={}):
resp = await client.post(
"/api/config/automation/config/moon",
data=json.dumps({"trigger": [], "action": [], "condition": []}),
)
await hass.async_block_till_done()
assert resp.status == 200
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):
"""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"]):
await async_setup_component(hass, "config", {})
assert await async_setup_component(hass, "config", {})
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(
"homeassistant.components.config._write", mock_write
):
), patch("homeassistant.config.async_hass_config_yaml", return_value={}):
resp = await client.delete("/api/config/automation/config/sun")
await hass.async_block_till_done()
assert resp.status == 200
result = await resp.json()
@ -135,3 +161,5 @@ async def test_delete_automation(hass, hass_client):
assert len(written) == 1
assert written[0][0]["id"] == "moon"
assert len(ent_reg.entities) == 1

View file

@ -1,6 +1,7 @@
"""Test Customize config panel."""
import json
from unittest.mock import patch
from asynctest import patch
from homeassistant.bootstrap import async_setup_component
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"})
with patch("homeassistant.components.config._read", mock_read), patch(
"homeassistant.components.config._write", mock_write
), patch(
"homeassistant.config.async_hass_config_yaml", return_value={},
):
resp = await client.post(
"/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"]}
),
)
await hass.async_block_till_done()
assert resp.status == 200
result = await resp.json()

View file

@ -61,6 +61,7 @@ async def test_update_device_config(hass, hass_client):
{"name": "Beer", "entities": ["light.top", "light.bottom"]}
),
)
await hass.async_block_till_done()
assert resp.status == 200
result = await resp.json()

View file

@ -1,6 +1,7 @@
"""Test Automation config panel."""
import json
from unittest.mock import patch
from asynctest import patch
from homeassistant.bootstrap import async_setup_component
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(
"homeassistant.components.config._write", mock_write
):
), patch("homeassistant.config.async_hass_config_yaml", return_value={}):
resp = await client.post(
"/api/config/scene/config/light_off",
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(
"homeassistant.components.config._write", mock_write
):
), patch("homeassistant.config.async_hass_config_yaml", return_value={}):
resp = await client.post(
"/api/config/scene/config/light_off",
data=json.dumps(
@ -114,8 +115,23 @@ async def test_bad_formatted_scene(hass, hass_client):
async def test_delete_scene(hass, hass_client):
"""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"]):
await async_setup_component(hass, "config", {})
assert await async_setup_component(hass, "config", {})
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(
"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")
await hass.async_block_till_done()
assert resp.status == 200
result = await resp.json()
@ -142,3 +159,5 @@ async def test_delete_scene(hass, hass_client):
assert len(written) == 1
assert written[0][0]["id"] == "light_off"
assert len(ent_reg.entities) == 1

View file

@ -3,7 +3,7 @@ import io
import unittest
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 tests.common import get_test_home_assistant
@ -128,3 +128,11 @@ class TestScene(unittest.TestCase):
assert self.light_1.is_on
assert self.light_2.is_on
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")