mirror of
https://github.com/home-assistant/core.git
synced 2025-07-20 19:57:07 +00:00
Use HassKey in lovelace (#136313)
* Use HassKey in lovelace * Improve type hints * docstring * Rename constant
This commit is contained in:
parent
ae65a81188
commit
73bd21e0ab
@ -1,5 +1,6 @@
|
|||||||
"""Support for the Lovelace UI."""
|
"""Support for the Lovelace UI."""
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
@ -29,6 +30,7 @@ from .const import ( # noqa: F401
|
|||||||
DEFAULT_ICON,
|
DEFAULT_ICON,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
EVENT_LOVELACE_UPDATED,
|
EVENT_LOVELACE_UPDATED,
|
||||||
|
LOVELACE_DATA,
|
||||||
MODE_STORAGE,
|
MODE_STORAGE,
|
||||||
MODE_YAML,
|
MODE_YAML,
|
||||||
RESOURCE_CREATE_FIELDS,
|
RESOURCE_CREATE_FIELDS,
|
||||||
@ -73,6 +75,16 @@ CONFIG_SCHEMA = vol.Schema(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class LovelaceData:
|
||||||
|
"""Dataclass to store information in hass.data."""
|
||||||
|
|
||||||
|
mode: str
|
||||||
|
dashboards: dict[str | None, dashboard.LovelaceConfig]
|
||||||
|
resources: resources.ResourceStorageCollection
|
||||||
|
yaml_dashboards: dict[str | None, ConfigType]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||||
"""Set up the Lovelace commands."""
|
"""Set up the Lovelace commands."""
|
||||||
mode = config[DOMAIN][CONF_MODE]
|
mode = config[DOMAIN][CONF_MODE]
|
||||||
@ -100,7 +112,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
resource_collection = await create_yaml_resource_col(
|
resource_collection = await create_yaml_resource_col(
|
||||||
hass, config[DOMAIN].get(CONF_RESOURCES)
|
hass, config[DOMAIN].get(CONF_RESOURCES)
|
||||||
)
|
)
|
||||||
hass.data[DOMAIN]["resources"] = resource_collection
|
hass.data[LOVELACE_DATA].resources = resource_collection
|
||||||
|
|
||||||
default_config: dashboard.LovelaceConfig
|
default_config: dashboard.LovelaceConfig
|
||||||
if mode == MODE_YAML:
|
if mode == MODE_YAML:
|
||||||
@ -151,13 +163,13 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
hass, websocket.websocket_lovelace_delete_config
|
hass, websocket.websocket_lovelace_delete_config
|
||||||
)
|
)
|
||||||
|
|
||||||
hass.data[DOMAIN] = {
|
hass.data[LOVELACE_DATA] = LovelaceData(
|
||||||
|
mode=mode,
|
||||||
# We store a dictionary mapping url_path: config. None is the default.
|
# We store a dictionary mapping url_path: config. None is the default.
|
||||||
"mode": mode,
|
dashboards={None: default_config},
|
||||||
"dashboards": {None: default_config},
|
resources=resource_collection,
|
||||||
"resources": resource_collection,
|
yaml_dashboards=config[DOMAIN].get(CONF_DASHBOARDS, {}),
|
||||||
"yaml_dashboards": config[DOMAIN].get(CONF_DASHBOARDS, {}),
|
)
|
||||||
}
|
|
||||||
|
|
||||||
if hass.config.recovery_mode:
|
if hass.config.recovery_mode:
|
||||||
return True
|
return True
|
||||||
@ -168,11 +180,11 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
|
|
||||||
if change_type == collection.CHANGE_REMOVED:
|
if change_type == collection.CHANGE_REMOVED:
|
||||||
frontend.async_remove_panel(hass, url_path)
|
frontend.async_remove_panel(hass, url_path)
|
||||||
await hass.data[DOMAIN]["dashboards"].pop(url_path).async_delete()
|
await hass.data[LOVELACE_DATA].dashboards.pop(url_path).async_delete()
|
||||||
return
|
return
|
||||||
|
|
||||||
if change_type == collection.CHANGE_ADDED:
|
if change_type == collection.CHANGE_ADDED:
|
||||||
existing = hass.data[DOMAIN]["dashboards"].get(url_path)
|
existing = hass.data[LOVELACE_DATA].dashboards.get(url_path)
|
||||||
|
|
||||||
if existing:
|
if existing:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
@ -182,13 +194,13 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
hass.data[DOMAIN]["dashboards"][url_path] = dashboard.LovelaceStorage(
|
hass.data[LOVELACE_DATA].dashboards[url_path] = dashboard.LovelaceStorage(
|
||||||
hass, item
|
hass, item
|
||||||
)
|
)
|
||||||
|
|
||||||
update = False
|
update = False
|
||||||
else:
|
else:
|
||||||
hass.data[DOMAIN]["dashboards"][url_path].config = item
|
hass.data[LOVELACE_DATA].dashboards[url_path].config = item
|
||||||
update = True
|
update = True
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -197,10 +209,10 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
_LOGGER.warning("Failed to %s panel %s from storage", change_type, url_path)
|
_LOGGER.warning("Failed to %s panel %s from storage", change_type, url_path)
|
||||||
|
|
||||||
# Process YAML dashboards
|
# Process YAML dashboards
|
||||||
for url_path, dashboard_conf in hass.data[DOMAIN]["yaml_dashboards"].items():
|
for url_path, dashboard_conf in hass.data[LOVELACE_DATA].yaml_dashboards.items():
|
||||||
# For now always mode=yaml
|
# For now always mode=yaml
|
||||||
lovelace_config = dashboard.LovelaceYAML(hass, url_path, dashboard_conf)
|
lovelace_config = dashboard.LovelaceYAML(hass, url_path, dashboard_conf)
|
||||||
hass.data[DOMAIN]["dashboards"][url_path] = lovelace_config
|
hass.data[LOVELACE_DATA].dashboards[url_path] = lovelace_config
|
||||||
|
|
||||||
try:
|
try:
|
||||||
_register_panel(hass, url_path, MODE_YAML, dashboard_conf, False)
|
_register_panel(hass, url_path, MODE_YAML, dashboard_conf, False)
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from pychromecast import Chromecast
|
from pychromecast import Chromecast
|
||||||
from pychromecast.const import CAST_TYPE_CHROMECAST
|
from pychromecast.const import CAST_TYPE_CHROMECAST
|
||||||
|
|
||||||
@ -23,8 +25,7 @@ from homeassistant.core import HomeAssistant, callback
|
|||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers.network import NoURLAvailableError, get_url
|
from homeassistant.helpers.network import NoURLAvailableError, get_url
|
||||||
|
|
||||||
from .const import DOMAIN, ConfigNotFound
|
from .const import DOMAIN, LOVELACE_DATA, ConfigNotFound
|
||||||
from .dashboard import LovelaceConfig
|
|
||||||
|
|
||||||
DEFAULT_DASHBOARD = "_default_"
|
DEFAULT_DASHBOARD = "_default_"
|
||||||
|
|
||||||
@ -76,7 +77,7 @@ async def async_browse_media(
|
|||||||
can_expand=False,
|
can_expand=False,
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
for url_path in hass.data[DOMAIN]["dashboards"]:
|
for url_path in hass.data[LOVELACE_DATA].dashboards:
|
||||||
if url_path is None:
|
if url_path is None:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -151,11 +152,13 @@ async def async_play_media(
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def _get_dashboard_info(hass, url_path):
|
async def _get_dashboard_info(
|
||||||
|
hass: HomeAssistant, url_path: str | None
|
||||||
|
) -> dict[str, Any]:
|
||||||
"""Load a dashboard and return info on views."""
|
"""Load a dashboard and return info on views."""
|
||||||
if url_path == DEFAULT_DASHBOARD:
|
if url_path == DEFAULT_DASHBOARD:
|
||||||
url_path = None
|
url_path = None
|
||||||
dashboard: LovelaceConfig | None = hass.data[DOMAIN]["dashboards"].get(url_path)
|
dashboard = hass.data[LOVELACE_DATA].dashboards.get(url_path)
|
||||||
|
|
||||||
if dashboard is None:
|
if dashboard is None:
|
||||||
raise ValueError("Invalid dashboard specified")
|
raise ValueError("Invalid dashboard specified")
|
||||||
@ -172,7 +175,7 @@ async def _get_dashboard_info(hass, url_path):
|
|||||||
url_path = dashboard.url_path
|
url_path = dashboard.url_path
|
||||||
title = config.get("title", url_path) if config else url_path
|
title = config.get("title", url_path) if config else url_path
|
||||||
|
|
||||||
views = []
|
views: list[dict[str, Any]] = []
|
||||||
data = {
|
data = {
|
||||||
"title": title,
|
"title": title,
|
||||||
"url_path": url_path,
|
"url_path": url_path,
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
"""Constants for Lovelace."""
|
"""Constants for Lovelace."""
|
||||||
|
|
||||||
from typing import Any
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING, Any
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -15,8 +17,13 @@ from homeassistant.exceptions import HomeAssistantError
|
|||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers.typing import VolDictType
|
from homeassistant.helpers.typing import VolDictType
|
||||||
from homeassistant.util import slugify
|
from homeassistant.util import slugify
|
||||||
|
from homeassistant.util.hass_dict import HassKey
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from . import LovelaceData
|
||||||
|
|
||||||
DOMAIN = "lovelace"
|
DOMAIN = "lovelace"
|
||||||
|
LOVELACE_DATA: HassKey[LovelaceData] = HassKey(DOMAIN)
|
||||||
|
|
||||||
DEFAULT_ICON = "hass:view-dashboard"
|
DEFAULT_ICON = "hass:view-dashboard"
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ from .const import (
|
|||||||
DOMAIN,
|
DOMAIN,
|
||||||
EVENT_LOVELACE_UPDATED,
|
EVENT_LOVELACE_UPDATED,
|
||||||
LOVELACE_CONFIG_FILE,
|
LOVELACE_CONFIG_FILE,
|
||||||
|
LOVELACE_DATA,
|
||||||
MODE_STORAGE,
|
MODE_STORAGE,
|
||||||
MODE_YAML,
|
MODE_YAML,
|
||||||
STORAGE_DASHBOARD_CREATE_FIELDS,
|
STORAGE_DASHBOARD_CREATE_FIELDS,
|
||||||
@ -315,7 +316,7 @@ class DashboardsCollectionWebSocket(collection.DictStorageCollectionWebsocket):
|
|||||||
msg["id"],
|
msg["id"],
|
||||||
[
|
[
|
||||||
dashboard.config
|
dashboard.config
|
||||||
for dashboard in hass.data[DOMAIN]["dashboards"].values()
|
for dashboard in hass.data[LOVELACE_DATA].dashboards.values()
|
||||||
if dashboard.config
|
if dashboard.config
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -1,12 +1,13 @@
|
|||||||
"""Provide info to system health."""
|
"""Provide info to system health."""
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant.components import system_health
|
from homeassistant.components import system_health
|
||||||
from homeassistant.const import CONF_MODE
|
from homeassistant.const import CONF_MODE
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
|
||||||
from .const import DOMAIN, MODE_AUTO, MODE_STORAGE, MODE_YAML
|
from .const import LOVELACE_DATA, MODE_AUTO, MODE_STORAGE, MODE_YAML
|
||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
@ -17,15 +18,17 @@ def async_register(
|
|||||||
register.async_register_info(system_health_info, "/config/lovelace")
|
register.async_register_info(system_health_info, "/config/lovelace")
|
||||||
|
|
||||||
|
|
||||||
async def system_health_info(hass):
|
async def system_health_info(hass: HomeAssistant) -> dict[str, Any]:
|
||||||
"""Get info for the info page."""
|
"""Get info for the info page."""
|
||||||
health_info = {"dashboards": len(hass.data[DOMAIN]["dashboards"])}
|
health_info: dict[str, Any] = {
|
||||||
health_info.update(await hass.data[DOMAIN]["resources"].async_get_info())
|
"dashboards": len(hass.data[LOVELACE_DATA].dashboards)
|
||||||
|
}
|
||||||
|
health_info.update(await hass.data[LOVELACE_DATA].resources.async_get_info())
|
||||||
|
|
||||||
dashboards_info = await asyncio.gather(
|
dashboards_info = await asyncio.gather(
|
||||||
*(
|
*(
|
||||||
hass.data[DOMAIN]["dashboards"][dashboard].async_get_info()
|
hass.data[LOVELACE_DATA].dashboards[dashboard].async_get_info()
|
||||||
for dashboard in hass.data[DOMAIN]["dashboards"]
|
for dashboard in hass.data[LOVELACE_DATA].dashboards
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -39,7 +42,7 @@ async def system_health_info(hass):
|
|||||||
else:
|
else:
|
||||||
health_info[key] = dashboard[key]
|
health_info[key] = dashboard[key]
|
||||||
|
|
||||||
if hass.data[DOMAIN][CONF_MODE] == MODE_YAML:
|
if hass.data[LOVELACE_DATA].mode == MODE_YAML:
|
||||||
health_info[CONF_MODE] = MODE_YAML
|
health_info[CONF_MODE] = MODE_YAML
|
||||||
elif MODE_STORAGE in modes:
|
elif MODE_STORAGE in modes:
|
||||||
health_info[CONF_MODE] = MODE_STORAGE
|
health_info[CONF_MODE] = MODE_STORAGE
|
||||||
|
@ -13,7 +13,7 @@ from homeassistant.exceptions import HomeAssistantError
|
|||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers.json import json_fragment
|
from homeassistant.helpers.json import json_fragment
|
||||||
|
|
||||||
from .const import CONF_URL_PATH, DOMAIN, ConfigNotFound
|
from .const import CONF_URL_PATH, LOVELACE_DATA, ConfigNotFound
|
||||||
from .dashboard import LovelaceStorage
|
from .dashboard import LovelaceStorage
|
||||||
|
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ def _handle_errors(func):
|
|||||||
msg: dict[str, Any],
|
msg: dict[str, Any],
|
||||||
) -> None:
|
) -> None:
|
||||||
url_path = msg.get(CONF_URL_PATH)
|
url_path = msg.get(CONF_URL_PATH)
|
||||||
config: LovelaceStorage | None = hass.data[DOMAIN]["dashboards"].get(url_path)
|
config = hass.data[LOVELACE_DATA].dashboards.get(url_path)
|
||||||
|
|
||||||
if config is None:
|
if config is None:
|
||||||
connection.send_error(
|
connection.send_error(
|
||||||
@ -74,7 +74,7 @@ async def websocket_lovelace_resources_impl(
|
|||||||
|
|
||||||
This function is called by both Storage and YAML mode WS handlers.
|
This function is called by both Storage and YAML mode WS handlers.
|
||||||
"""
|
"""
|
||||||
resources = hass.data[DOMAIN]["resources"]
|
resources = hass.data[LOVELACE_DATA].resources
|
||||||
|
|
||||||
if hass.config.safe_mode:
|
if hass.config.safe_mode:
|
||||||
connection.send_result(msg["id"], [])
|
connection.send_result(msg["id"], [])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user