Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """The Home Assistant alerts integration."""
2 
3 from __future__ import annotations
4 
5 import logging
6 
7 from homeassistant.const import EVENT_COMPONENT_LOADED
8 from homeassistant.core import Event, HomeAssistant, callback
9 from homeassistant.helpers import config_validation as cv
10 from homeassistant.helpers.aiohttp_client import async_get_clientsession
11 from homeassistant.helpers.debounce import Debouncer
13  IssueSeverity,
14  async_create_issue,
15  async_delete_issue,
16 )
17 from homeassistant.helpers.start import async_at_started
18 from homeassistant.helpers.typing import ConfigType
19 from homeassistant.setup import EventComponentLoaded
20 
21 from .const import COMPONENT_LOADED_COOLDOWN, DOMAIN, REQUEST_TIMEOUT
22 from .coordinator import AlertUpdateCoordinator
23 
24 _LOGGER = logging.getLogger(__name__)
25 
26 CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
27 
28 
29 async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
30  """Set up alerts."""
31  last_alerts: dict[str, str | None] = {}
32 
33  async def async_update_alerts() -> None:
34  nonlocal last_alerts
35 
36  active_alerts: dict[str, str | None] = {}
37 
38  for issue_id, alert in coordinator.data.items():
39  # Skip creation if already created and not updated since then
40  if issue_id in last_alerts and alert.date_updated == last_alerts[issue_id]:
41  active_alerts[issue_id] = alert.date_updated
42  continue
43 
44  # Fetch alert to get title + description
45  try:
46  response = await async_get_clientsession(hass).get(
47  f"https://alerts.home-assistant.io/alerts/{alert.alert_id}.json",
48  timeout=REQUEST_TIMEOUT,
49  )
50  except TimeoutError:
51  _LOGGER.warning("Error fetching %s: timeout", alert.filename)
52  continue
53 
54  alert_content = await response.json()
56  hass,
57  DOMAIN,
58  issue_id,
59  is_fixable=False,
60  issue_domain=alert.integration,
61  severity=IssueSeverity.WARNING,
62  translation_key="alert",
63  translation_placeholders={
64  "title": alert_content["title"],
65  "description": alert_content["content"],
66  },
67  )
68  active_alerts[issue_id] = alert.date_updated
69 
70  inactive_alerts = last_alerts.keys() - active_alerts.keys()
71  for issue_id in inactive_alerts:
72  async_delete_issue(hass, DOMAIN, issue_id)
73 
74  last_alerts = active_alerts
75 
76  @callback
77  def async_schedule_update_alerts() -> None:
78  if not coordinator.last_update_success:
79  return
80 
81  hass.async_create_background_task(
82  async_update_alerts(), "homeassistant_alerts update", eager_start=True
83  )
84 
85  coordinator = AlertUpdateCoordinator(hass)
86  coordinator.async_add_listener(async_schedule_update_alerts)
87 
88  async def initial_refresh(hass: HomeAssistant) -> None:
89  refresh_debouncer = Debouncer(
90  hass,
91  _LOGGER,
92  cooldown=COMPONENT_LOADED_COOLDOWN,
93  immediate=False,
94  function=coordinator.async_refresh,
95  background=True,
96  )
97 
98  @callback
99  def _component_loaded(_: Event[EventComponentLoaded]) -> None:
100  refresh_debouncer.async_schedule_call()
101 
102  await coordinator.async_refresh()
103  hass.bus.async_listen(EVENT_COMPONENT_LOADED, _component_loaded)
104 
105  async_at_started(hass, initial_refresh)
106 
107  return True
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
bool async_setup(HomeAssistant hass, ConfigType config)
Definition: __init__.py:29
None async_create_issue(HomeAssistant hass, str entry_id)
Definition: repairs.py:69
None async_delete_issue(HomeAssistant hass, str entry_id)
Definition: repairs.py:85
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)
CALLBACK_TYPE async_at_started(HomeAssistant hass, Callable[[HomeAssistant], Coroutine[Any, Any, None]|None] at_start_cb)
Definition: start.py:80