"""Websocket API for Lovelace.""" from functools import wraps import voluptuous as vol from homeassistant.components import websocket_api from homeassistant.core import callback from homeassistant.exceptions import HomeAssistantError from homeassistant.helpers import config_validation as cv from .const import CONF_URL_PATH, DOMAIN, ConfigNotFound def _handle_errors(func): """Handle error with WebSocket calls.""" @wraps(func) async def send_with_error_handling(hass, connection, msg): url_path = msg.get(CONF_URL_PATH) config = hass.data[DOMAIN]["dashboards"].get(url_path) if config is None: connection.send_error( msg["id"], "config_not_found", f"Unknown config specified: {url_path}" ) return error = None try: result = await func(hass, connection, msg, config) except ConfigNotFound: error = "config_not_found", "No config found." except HomeAssistantError as err: error = "error", str(err) if error is not None: connection.send_error(msg["id"], *error) return if msg is not None: await connection.send_big_result(msg["id"], result) else: connection.send_result(msg["id"], result) return send_with_error_handling @websocket_api.async_response @websocket_api.websocket_command({"type": "lovelace/resources"}) async def websocket_lovelace_resources(hass, connection, msg): """Send Lovelace UI resources over WebSocket configuration.""" resources = hass.data[DOMAIN]["resources"] if not resources.loaded: await resources.async_load() resources.loaded = True connection.send_result(msg["id"], resources.async_items()) @websocket_api.async_response @websocket_api.websocket_command( { "type": "lovelace/config", vol.Optional("force", default=False): bool, vol.Optional(CONF_URL_PATH): vol.Any(None, cv.string), } ) @_handle_errors async def websocket_lovelace_config(hass, connection, msg, config): """Send Lovelace UI config over WebSocket configuration.""" return await config.async_load(msg["force"]) @websocket_api.require_admin @websocket_api.async_response @websocket_api.websocket_command( { "type": "lovelace/config/save", "config": vol.Any(str, dict), vol.Optional(CONF_URL_PATH): vol.Any(None, cv.string), } ) @_handle_errors async def websocket_lovelace_save_config(hass, connection, msg, config): """Save Lovelace UI configuration.""" await config.async_save(msg["config"]) @websocket_api.require_admin @websocket_api.async_response @websocket_api.websocket_command( { "type": "lovelace/config/delete", vol.Optional(CONF_URL_PATH): vol.Any(None, cv.string), } ) @_handle_errors async def websocket_lovelace_delete_config(hass, connection, msg, config): """Delete Lovelace UI configuration.""" await config.async_delete() @websocket_api.websocket_command({"type": "lovelace/dashboards/list"}) @callback def websocket_lovelace_dashboards(hass, connection, msg): """Delete Lovelace UI configuration.""" connection.send_result( msg["id"], [ dashboard.config for dashboard in hass.data[DOMAIN]["dashboards"].values() if dashboard.config ], )