Catch device not found in device automations (#31401)
parent
55aa341dab
commit
7127310f10
|
@ -1,5 +1,6 @@
|
||||||
"""Helpers for device automations."""
|
"""Helpers for device automations."""
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from functools import wraps
|
||||||
import logging
|
import logging
|
||||||
from types import ModuleType
|
from types import ModuleType
|
||||||
from typing import Any, List, MutableMapping
|
from typing import Any, List, MutableMapping
|
||||||
|
@ -14,7 +15,7 @@ from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers.entity_registry import async_entries_for_device
|
from homeassistant.helpers.entity_registry import async_entries_for_device
|
||||||
from homeassistant.loader import IntegrationNotFound, async_get_integration
|
from homeassistant.loader import IntegrationNotFound, async_get_integration
|
||||||
|
|
||||||
from .exceptions import InvalidDeviceAutomationConfig
|
from .exceptions import DeviceNotFound, InvalidDeviceAutomationConfig
|
||||||
|
|
||||||
# mypy: allow-untyped-calls, allow-untyped-defs
|
# mypy: allow-untyped-calls, allow-untyped-defs
|
||||||
|
|
||||||
|
@ -117,6 +118,10 @@ async def _async_get_device_automations(hass, automation_type, device_id):
|
||||||
domains = set()
|
domains = set()
|
||||||
automations: List[MutableMapping[str, Any]] = []
|
automations: List[MutableMapping[str, Any]] = []
|
||||||
device = device_registry.async_get(device_id)
|
device = device_registry.async_get(device_id)
|
||||||
|
|
||||||
|
if device is None:
|
||||||
|
raise DeviceNotFound
|
||||||
|
|
||||||
for entry_id in device.config_entries:
|
for entry_id in device.config_entries:
|
||||||
config_entry = hass.config_entries.async_get_entry(entry_id)
|
config_entry = hass.config_entries.async_get_entry(entry_id)
|
||||||
domains.add(config_entry.domain)
|
domains.add(config_entry.domain)
|
||||||
|
@ -173,6 +178,21 @@ async def _async_get_device_automation_capabilities(hass, automation_type, autom
|
||||||
return capabilities
|
return capabilities
|
||||||
|
|
||||||
|
|
||||||
|
def handle_device_errors(func):
|
||||||
|
"""Handle device automation errors."""
|
||||||
|
|
||||||
|
@wraps(func)
|
||||||
|
async def with_error_handling(hass, connection, msg):
|
||||||
|
try:
|
||||||
|
await func(hass, connection, msg)
|
||||||
|
except DeviceNotFound:
|
||||||
|
connection.send_error(
|
||||||
|
msg["id"], websocket_api.const.ERR_NOT_FOUND, "Device not found"
|
||||||
|
)
|
||||||
|
|
||||||
|
return with_error_handling
|
||||||
|
|
||||||
|
|
||||||
@websocket_api.websocket_command(
|
@websocket_api.websocket_command(
|
||||||
{
|
{
|
||||||
vol.Required("type"): "device_automation/action/list",
|
vol.Required("type"): "device_automation/action/list",
|
||||||
|
@ -180,6 +200,7 @@ async def _async_get_device_automation_capabilities(hass, automation_type, autom
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@websocket_api.async_response
|
@websocket_api.async_response
|
||||||
|
@handle_device_errors
|
||||||
async def websocket_device_automation_list_actions(hass, connection, msg):
|
async def websocket_device_automation_list_actions(hass, connection, msg):
|
||||||
"""Handle request for device actions."""
|
"""Handle request for device actions."""
|
||||||
device_id = msg["device_id"]
|
device_id = msg["device_id"]
|
||||||
|
@ -194,6 +215,7 @@ async def websocket_device_automation_list_actions(hass, connection, msg):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@websocket_api.async_response
|
@websocket_api.async_response
|
||||||
|
@handle_device_errors
|
||||||
async def websocket_device_automation_list_conditions(hass, connection, msg):
|
async def websocket_device_automation_list_conditions(hass, connection, msg):
|
||||||
"""Handle request for device conditions."""
|
"""Handle request for device conditions."""
|
||||||
device_id = msg["device_id"]
|
device_id = msg["device_id"]
|
||||||
|
@ -208,6 +230,7 @@ async def websocket_device_automation_list_conditions(hass, connection, msg):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@websocket_api.async_response
|
@websocket_api.async_response
|
||||||
|
@handle_device_errors
|
||||||
async def websocket_device_automation_list_triggers(hass, connection, msg):
|
async def websocket_device_automation_list_triggers(hass, connection, msg):
|
||||||
"""Handle request for device triggers."""
|
"""Handle request for device triggers."""
|
||||||
device_id = msg["device_id"]
|
device_id = msg["device_id"]
|
||||||
|
@ -222,6 +245,7 @@ async def websocket_device_automation_list_triggers(hass, connection, msg):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@websocket_api.async_response
|
@websocket_api.async_response
|
||||||
|
@handle_device_errors
|
||||||
async def websocket_device_automation_get_action_capabilities(hass, connection, msg):
|
async def websocket_device_automation_get_action_capabilities(hass, connection, msg):
|
||||||
"""Handle request for device action capabilities."""
|
"""Handle request for device action capabilities."""
|
||||||
action = msg["action"]
|
action = msg["action"]
|
||||||
|
@ -238,6 +262,7 @@ async def websocket_device_automation_get_action_capabilities(hass, connection,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@websocket_api.async_response
|
@websocket_api.async_response
|
||||||
|
@handle_device_errors
|
||||||
async def websocket_device_automation_get_condition_capabilities(hass, connection, msg):
|
async def websocket_device_automation_get_condition_capabilities(hass, connection, msg):
|
||||||
"""Handle request for device condition capabilities."""
|
"""Handle request for device condition capabilities."""
|
||||||
condition = msg["condition"]
|
condition = msg["condition"]
|
||||||
|
@ -254,6 +279,7 @@ async def websocket_device_automation_get_condition_capabilities(hass, connectio
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@websocket_api.async_response
|
@websocket_api.async_response
|
||||||
|
@handle_device_errors
|
||||||
async def websocket_device_automation_get_trigger_capabilities(hass, connection, msg):
|
async def websocket_device_automation_get_trigger_capabilities(hass, connection, msg):
|
||||||
"""Handle request for device trigger capabilities."""
|
"""Handle request for device trigger capabilities."""
|
||||||
trigger = msg["trigger"]
|
trigger = msg["trigger"]
|
||||||
|
|
|
@ -4,3 +4,7 @@ from homeassistant.exceptions import HomeAssistantError
|
||||||
|
|
||||||
class InvalidDeviceAutomationConfig(HomeAssistantError):
|
class InvalidDeviceAutomationConfig(HomeAssistantError):
|
||||||
"""When device automation config is invalid."""
|
"""When device automation config is invalid."""
|
||||||
|
|
||||||
|
|
||||||
|
class DeviceNotFound(HomeAssistantError):
|
||||||
|
"""When referenced device not found."""
|
||||||
|
|
|
@ -761,3 +761,17 @@ async def test_automation_with_bad_trigger(hass, caplog):
|
||||||
)
|
)
|
||||||
|
|
||||||
assert "required key not provided" in caplog.text
|
assert "required key not provided" in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
async def test_websocket_device_not_found(hass, hass_ws_client):
|
||||||
|
"""Test caling command with unknown device."""
|
||||||
|
await async_setup_component(hass, "device_automation", {})
|
||||||
|
client = await hass_ws_client(hass)
|
||||||
|
await client.send_json(
|
||||||
|
{"id": 1, "type": "device_automation/action/list", "device_id": "non-existing"}
|
||||||
|
)
|
||||||
|
msg = await client.receive_json()
|
||||||
|
|
||||||
|
assert msg["id"] == 1
|
||||||
|
assert not msg["success"]
|
||||||
|
assert msg["error"] == {"code": "not_found", "message": "Device not found"}
|
||||||
|
|
Loading…
Reference in New Issue