130 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
"""Lovelace resources support."""
 | 
						|
from __future__ import annotations
 | 
						|
 | 
						|
import logging
 | 
						|
from typing import Optional, cast
 | 
						|
import uuid
 | 
						|
 | 
						|
import voluptuous as vol
 | 
						|
 | 
						|
from homeassistant.const import CONF_RESOURCES, CONF_TYPE
 | 
						|
from homeassistant.core import HomeAssistant, callback
 | 
						|
from homeassistant.exceptions import HomeAssistantError
 | 
						|
from homeassistant.helpers import collection, storage
 | 
						|
 | 
						|
from .const import (
 | 
						|
    CONF_RESOURCE_TYPE_WS,
 | 
						|
    DOMAIN,
 | 
						|
    RESOURCE_CREATE_FIELDS,
 | 
						|
    RESOURCE_SCHEMA,
 | 
						|
    RESOURCE_UPDATE_FIELDS,
 | 
						|
)
 | 
						|
from .dashboard import LovelaceConfig
 | 
						|
 | 
						|
RESOURCE_STORAGE_KEY = f"{DOMAIN}_resources"
 | 
						|
RESOURCES_STORAGE_VERSION = 1
 | 
						|
_LOGGER = logging.getLogger(__name__)
 | 
						|
 | 
						|
 | 
						|
class ResourceYAMLCollection:
 | 
						|
    """Collection representing static YAML."""
 | 
						|
 | 
						|
    loaded = True
 | 
						|
 | 
						|
    def __init__(self, data):
 | 
						|
        """Initialize a resource YAML collection."""
 | 
						|
        self.data = data
 | 
						|
 | 
						|
    async def async_get_info(self):
 | 
						|
        """Return the resources info for YAML mode."""
 | 
						|
        return {"resources": len(self.async_items() or [])}
 | 
						|
 | 
						|
    @callback
 | 
						|
    def async_items(self) -> list[dict]:
 | 
						|
        """Return list of items in collection."""
 | 
						|
        return self.data
 | 
						|
 | 
						|
 | 
						|
class ResourceStorageCollection(collection.StorageCollection):
 | 
						|
    """Collection to store resources."""
 | 
						|
 | 
						|
    loaded = False
 | 
						|
    CREATE_SCHEMA = vol.Schema(RESOURCE_CREATE_FIELDS)
 | 
						|
    UPDATE_SCHEMA = vol.Schema(RESOURCE_UPDATE_FIELDS)
 | 
						|
 | 
						|
    def __init__(self, hass: HomeAssistant, ll_config: LovelaceConfig) -> None:
 | 
						|
        """Initialize the storage collection."""
 | 
						|
        super().__init__(
 | 
						|
            storage.Store(hass, RESOURCES_STORAGE_VERSION, RESOURCE_STORAGE_KEY),
 | 
						|
            _LOGGER,
 | 
						|
        )
 | 
						|
        self.ll_config = ll_config
 | 
						|
 | 
						|
    async def async_get_info(self):
 | 
						|
        """Return the resources info for YAML mode."""
 | 
						|
        if not self.loaded:
 | 
						|
            await self.async_load()
 | 
						|
            self.loaded = True
 | 
						|
 | 
						|
        return {"resources": len(self.async_items() or [])}
 | 
						|
 | 
						|
    async def _async_load_data(self) -> dict | None:
 | 
						|
        """Load the data."""
 | 
						|
        data = await self.store.async_load()
 | 
						|
 | 
						|
        if data is not None:
 | 
						|
            return cast(Optional[dict], data)
 | 
						|
 | 
						|
        # Import it from config.
 | 
						|
        try:
 | 
						|
            conf = await self.ll_config.async_load(False)
 | 
						|
        except HomeAssistantError:
 | 
						|
            return None
 | 
						|
 | 
						|
        if CONF_RESOURCES not in conf:
 | 
						|
            return None
 | 
						|
 | 
						|
        # Remove it from config and save both resources + config
 | 
						|
        data = conf[CONF_RESOURCES]
 | 
						|
 | 
						|
        try:
 | 
						|
            vol.Schema([RESOURCE_SCHEMA])(data)
 | 
						|
        except vol.Invalid as err:
 | 
						|
            _LOGGER.warning("Resource import failed. Data invalid: %s", err)
 | 
						|
            return None
 | 
						|
 | 
						|
        conf.pop(CONF_RESOURCES)
 | 
						|
 | 
						|
        for item in data:
 | 
						|
            item[collection.CONF_ID] = uuid.uuid4().hex
 | 
						|
 | 
						|
        data = {"items": data}
 | 
						|
 | 
						|
        await self.store.async_save(data)
 | 
						|
        await self.ll_config.async_save(conf)
 | 
						|
 | 
						|
        return data
 | 
						|
 | 
						|
    async def _process_create_data(self, data: dict) -> dict:
 | 
						|
        """Validate the config is valid."""
 | 
						|
        data = self.CREATE_SCHEMA(data)
 | 
						|
        data[CONF_TYPE] = data.pop(CONF_RESOURCE_TYPE_WS)
 | 
						|
        return data
 | 
						|
 | 
						|
    @callback
 | 
						|
    def _get_suggested_id(self, info: dict) -> str:
 | 
						|
        """Return unique ID."""
 | 
						|
        return uuid.uuid4().hex
 | 
						|
 | 
						|
    async def _update_data(self, data: dict, update_data: dict) -> dict:
 | 
						|
        """Return a new updated data object."""
 | 
						|
        if not self.loaded:
 | 
						|
            await self.async_load()
 | 
						|
            self.loaded = True
 | 
						|
 | 
						|
        update_data = self.UPDATE_SCHEMA(update_data)
 | 
						|
        if CONF_RESOURCE_TYPE_WS in update_data:
 | 
						|
            update_data[CONF_TYPE] = update_data.pop(CONF_RESOURCE_TYPE_WS)
 | 
						|
 | 
						|
        return {**data, **update_data}
 |