Files
home-assistant-alt/hass/settings/custom_components/yandex_smart_home/helpers.py
T
2024-01-11 15:10:51 +03:00

149 lines
4.7 KiB
Python

"""Helper classes for Yandex Smart Home integration."""
from __future__ import annotations
from typing import Any
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import Context, HomeAssistant, callback
from homeassistant.helpers.entityfilter import EntityFilter
from homeassistant.helpers.storage import Store
from homeassistant.helpers.typing import ConfigType
from . import const
from .const import DOMAIN, NOTIFIERS, STORE_CACHE_ATTRS
class Config:
"""Hold the configuration for Yandex Smart Home."""
def __init__(self,
hass: HomeAssistant,
entry: ConfigEntry,
entity_config: dict[str, Any] | None = None,
entity_filter: EntityFilter | None = None):
"""Initialize the configuration."""
self._hass = hass
self._data = entry.data
self._options = entry.options
self._entity_filter = entity_filter
self.cache: CacheStore | None = None
self.entity_config = entity_config or {}
async def async_init(self):
self.cache = CacheStore(self._hass)
await self.cache.async_load()
@property
def is_reporting_state(self) -> bool:
"""Return if we're actively reporting states."""
if self.is_cloud_connection:
return True
return bool(self._hass.data[DOMAIN][NOTIFIERS])
@property
def is_cloud_connection(self) -> bool:
return self._data[const.CONF_CONNECTION_TYPE] == const.CONNECTION_TYPE_CLOUD
@property
def is_direct_connection(self) -> bool:
return self._data[const.CONF_CONNECTION_TYPE] == const.CONNECTION_TYPE_DIRECT
@property
def use_cloud_stream(self) -> bool:
return self._options[const.CONF_CLOUD_STREAM]
@property
def cloud_instance_id(self) -> str | None:
return self._data[const.CONF_CLOUD_INSTANCE][const.CONF_CLOUD_INSTANCE_ID]
@property
def cloud_connection_token(self) -> str | None:
return self._data[const.CONF_CLOUD_INSTANCE][const.CONF_CLOUD_INSTANCE_CONNECTION_TOKEN]
@property
def user_id(self) -> str | None:
"""User id for service calls, used only in cloud connection."""
return self._options.get(const.CONF_USER_ID)
@property
def pressure_unit(self) -> str:
return self._options[const.CONF_PRESSURE_UNIT]
@property
def beta(self) -> bool:
return self._options[const.CONF_BETA] # pragma: no cover
@property
def notifier(self) -> list[ConfigType]:
return self._data.get(const.CONF_NOTIFIER, [])
@property
def color_profiles(self) -> dict[str, dict[str, int]]:
return self._options.get(const.CONF_COLOR_PROFILE, {})
@property
def devices_discovered(self) -> bool:
return self._data[const.CONF_DEVICES_DISCOVERED]
def get_entity_config(self, entity_id: str) -> dict[str, Any]:
return self.entity_config.get(entity_id, {})
def should_expose(self, entity_id: str) -> bool:
if self._entity_filter and not self._entity_filter.empty_filter:
return self._entity_filter(entity_id)
return False
class CacheStore:
_STORAGE_VERSION = 1
_STORAGE_KEY = f'{DOMAIN}.cache'
def __init__(self, hass):
self._hass = hass
self._store = Store(hass, self._STORAGE_VERSION, self._STORAGE_KEY)
self._data = {STORE_CACHE_ATTRS: {}}
def get_attr_value(self, entity_id: str, attr: str) -> Any | None:
"""Return a cached value of attribute for entity."""
if entity_id not in self._data[STORE_CACHE_ATTRS]:
return None
return self._data[STORE_CACHE_ATTRS][entity_id].get(attr)
@callback
def save_attr_value(self, entity_id: str, attr: str, value: Any):
"""Cache entity's attribute value to disk."""
if entity_id not in self._data[STORE_CACHE_ATTRS]:
self._data[STORE_CACHE_ATTRS][entity_id] = {}
has_changed = True
else:
has_changed = self._data[STORE_CACHE_ATTRS][entity_id][attr] != value
self._data[STORE_CACHE_ATTRS][entity_id][attr] = value
if has_changed:
self._store.async_delay_save(lambda: self._data, 5.0)
async def async_load(self):
data = await self._store.async_load()
if data:
self._data = data
class RequestData:
"""Hold data associated with a particular request."""
def __init__(self,
config: Config,
request_user_id: str | None,
request_id: str | None = None,
user_id: str | None = None):
"""Initialize the request data."""
self.config = config
self.context = Context(user_id=user_id)
self.request_user_id = request_user_id
self.request_id = request_id