1 """Icon helper methods."""
3 from __future__
import annotations
6 from collections.abc
import Iterable
7 from functools
import lru_cache
10 from typing
import Any, cast
17 from .translation
import build_resources
19 ICON_CACHE: HassKey[_IconsCache] =
HassKey(
"icon_cache")
21 _LOGGER = logging.getLogger(__name__)
25 value: str | dict[str, str | dict[str, str]],
26 ) -> dict[str, str | dict[str, str]]:
27 """Convert shorthand service icon to dict."""
28 if isinstance(value, str):
29 return {
"service": value}
34 icons_file: pathlib.Path,
36 """Load and parse an icons.json file."""
38 if "services" not in icons:
40 services = cast(dict[str, str | dict[str, str | dict[str, str]]], icons[
"services"])
41 for service, service_icons
in services.items():
47 icons_files: dict[str, pathlib.Path],
48 ) -> dict[str, dict[str, Any]]:
49 """Load and parse icons.json files."""
52 for component, icons_file
in icons_files.items()
59 integrations: dict[str, Integration],
62 icons: dict[str, Any] = {}
66 comp: integrations[comp].file_path /
"icons.json" for comp
in components
72 await hass.async_add_executor_job(_load_icons_files, files_to_load)
79 """Cache for icons."""
81 __slots__ = (
"_hass",
"_loaded",
"_cache",
"_lock")
83 def __init__(self, hass: HomeAssistant) ->
None:
84 """Initialize the cache."""
86 self._loaded: set[str] = set()
87 self._cache: dict[str, dict[str, Any]] = {}
88 self.
_lock_lock = asyncio.Lock()
94 ) -> dict[str, dict[str, Any]]:
95 """Load resources into the cache."""
96 if components_to_load := components - self._loaded:
99 async
with self.
_lock_lock:
102 if components_to_load := components - self._loaded:
103 await self.
_async_load_async_load(components_to_load)
107 for component
in components
108 if (result := self._cache.
get(category, {}).
get(component))
112 """Populate the cache for a given set of components."""
113 _LOGGER.debug(
"Cache miss for: %s", components)
115 integrations: dict[str, Integration] = {}
117 for domain, int_or_exc
in ints_or_excs.items():
118 if isinstance(int_or_exc, Exception):
120 integrations[domain] = int_or_exc
125 self._loaded.
update(components)
130 components: set[str],
131 icons: dict[str, dict[str, Any]],
133 """Extract resources into the cache."""
135 category
for component
in icons.values()
for category
in component
137 for category
in categories:
138 self._cache.setdefault(category, {}).
update(
146 integrations: Iterable[str] |
None =
None,
148 """Return all icons of integrations.
150 If integration specified, load it for that one; otherwise default to loaded
154 components = set(integrations)
156 components = hass.config.top_level_components
158 if ICON_CACHE
in hass.data:
159 cache = hass.data[ICON_CACHE]
163 return await cache.async_fetch(category, components)
168 battery_level: int |
None =
None, charging: bool =
False
170 """Return a battery icon valid identifier."""
172 if battery_level
is None:
173 return f
"{icon}-unknown"
174 if charging
and battery_level > 10:
175 icon += f
"-charging-{int(round(battery_level / 20 - 0.01)) * 20}"
178 elif battery_level <= 5:
180 elif 5 < battery_level < 95:
181 icon += f
"-{int(round(battery_level / 10 - 0.01)) * 10}"
186 """Return a signal icon valid identifier."""
187 if signal_level
is None or signal_level == 0:
188 return "mdi:signal-cellular-outline"
189 if signal_level > 70:
190 return "mdi:signal-cellular-3"
191 if signal_level > 30:
192 return "mdi:signal-cellular-2"
193 return "mdi:signal-cellular-1"
None _async_load(self, set[str] components)
None __init__(self, HomeAssistant hass)
None _build_category_cache(self, set[str] components, dict[str, dict[str, Any]] icons)
dict[str, dict[str, Any]] async_fetch(self, str category, set[str] components)
web.Response get(self, web.Request request, str config_key)
IssData update(pyiss.ISS iss)
dict[str, Any] async_get_icons(HomeAssistant hass, str category, Iterable[str]|None integrations=None)
dict[str, Any] _async_get_component_icons(HomeAssistant hass, set[str] components, dict[str, Integration] integrations)
dict[str, str|dict[str, str]] convert_shorthand_service_icon(str|dict[str, str|dict[str, str]] value)
str icon_for_battery_level(int|None battery_level=None, bool charging=False)
dict[str, Any] _load_icons_file(pathlib.Path icons_file)
str icon_for_signal_level(int|None signal_level=None)
dict[str, dict[str, Any]] _load_icons_files(dict[str, pathlib.Path] icons_files)
dict[str, dict[str, Any]|str] build_resources(dict[str, dict[str, dict[str, Any]|str]] translation_strings, set[str] components, str category)
dict[str, Integration|Exception] async_get_integrations(HomeAssistant hass, Iterable[str] domains)
JsonObjectType load_json_object(str|PathLike[str] filename, JsonObjectType default=_SENTINEL)