Home Assistant Unofficial Reference 2024.12.1
__init__.py
Go to the documentation of this file.
1 """Support for Canary devices."""
2 
3 from __future__ import annotations
4 
5 from datetime import timedelta
6 import logging
7 from typing import Final
8 
9 from canary.api import Api
10 from requests.exceptions import ConnectTimeout, HTTPError
11 import voluptuous as vol
12 
13 from homeassistant.components.camera import DOMAIN as CAMERA_DOMAIN
14 from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
15 from homeassistant.const import CONF_PASSWORD, CONF_TIMEOUT, CONF_USERNAME, Platform
16 from homeassistant.core import HomeAssistant
17 from homeassistant.exceptions import ConfigEntryNotReady
19 from homeassistant.helpers.typing import ConfigType
20 
21 from .const import (
22  CONF_FFMPEG_ARGUMENTS,
23  DATA_COORDINATOR,
24  DATA_UNDO_UPDATE_LISTENER,
25  DEFAULT_FFMPEG_ARGUMENTS,
26  DEFAULT_TIMEOUT,
27  DOMAIN,
28 )
29 from .coordinator import CanaryDataUpdateCoordinator
30 
31 _LOGGER: Final = logging.getLogger(__name__)
32 
33 MIN_TIME_BETWEEN_UPDATES: Final = timedelta(seconds=30)
34 
35 CONFIG_SCHEMA: Final = vol.Schema(
36  vol.All(
37  cv.deprecated(DOMAIN),
38  {
39  DOMAIN: vol.Schema(
40  {
41  vol.Required(CONF_USERNAME): cv.string,
42  vol.Required(CONF_PASSWORD): cv.string,
43  vol.Optional(
44  CONF_TIMEOUT, default=DEFAULT_TIMEOUT
45  ): cv.positive_int,
46  }
47  )
48  },
49  ),
50  extra=vol.ALLOW_EXTRA,
51 )
52 
53 PLATFORMS: Final[list[Platform]] = [
54  Platform.ALARM_CONTROL_PANEL,
55  Platform.CAMERA,
56  Platform.SENSOR,
57 ]
58 
59 
60 async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
61  """Set up the Canary integration."""
62  hass.data.setdefault(DOMAIN, {})
63 
64  if hass.config_entries.async_entries(DOMAIN):
65  return True
66 
67  ffmpeg_arguments = DEFAULT_FFMPEG_ARGUMENTS
68  if CAMERA_DOMAIN in config:
69  camera_config = next(
70  (item for item in config[CAMERA_DOMAIN] if item["platform"] == DOMAIN),
71  None,
72  )
73 
74  if camera_config:
75  ffmpeg_arguments = camera_config.get(
76  CONF_FFMPEG_ARGUMENTS, DEFAULT_FFMPEG_ARGUMENTS
77  )
78 
79  if DOMAIN in config:
80  if ffmpeg_arguments != DEFAULT_FFMPEG_ARGUMENTS:
81  config[DOMAIN][CONF_FFMPEG_ARGUMENTS] = ffmpeg_arguments
82 
83  hass.async_create_task(
84  hass.config_entries.flow.async_init(
85  DOMAIN,
86  context={"source": SOURCE_IMPORT},
87  data=config[DOMAIN],
88  )
89  )
90  return True
91 
92 
93 async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
94  """Set up Canary from a config entry."""
95  if not entry.options:
96  options = {
97  CONF_FFMPEG_ARGUMENTS: entry.data.get(
98  CONF_FFMPEG_ARGUMENTS, DEFAULT_FFMPEG_ARGUMENTS
99  ),
100  CONF_TIMEOUT: entry.data.get(CONF_TIMEOUT, DEFAULT_TIMEOUT),
101  }
102  hass.config_entries.async_update_entry(entry, options=options)
103 
104  try:
105  canary_api = await hass.async_add_executor_job(_get_canary_api_instance, entry)
106  except (ConnectTimeout, HTTPError) as error:
107  _LOGGER.error("Unable to connect to Canary service: %s", str(error))
108  raise ConfigEntryNotReady from error
109 
110  coordinator = CanaryDataUpdateCoordinator(hass, api=canary_api)
111  await coordinator.async_config_entry_first_refresh()
112 
113  undo_listener = entry.add_update_listener(_async_update_listener)
114 
115  hass.data[DOMAIN][entry.entry_id] = {
116  DATA_COORDINATOR: coordinator,
117  DATA_UNDO_UPDATE_LISTENER: undo_listener,
118  }
119 
120  await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
121 
122  return True
123 
124 
125 async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
126  """Unload a config entry."""
127  unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
128 
129  if unload_ok:
130  hass.data[DOMAIN][entry.entry_id][DATA_UNDO_UPDATE_LISTENER]()
131  hass.data[DOMAIN].pop(entry.entry_id)
132 
133  return unload_ok
134 
135 
136 async def _async_update_listener(hass: HomeAssistant, entry: ConfigEntry) -> None:
137  """Handle options update."""
138  await hass.config_entries.async_reload(entry.entry_id)
139 
140 
141 def _get_canary_api_instance(entry: ConfigEntry) -> Api:
142  """Initialize a new instance of CanaryApi."""
143  return Api(
144  entry.data[CONF_USERNAME],
145  entry.data[CONF_PASSWORD],
146  entry.options.get(CONF_TIMEOUT, DEFAULT_TIMEOUT),
147  )
None _async_update_listener(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:136
bool async_setup_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:93
bool async_unload_entry(HomeAssistant hass, ConfigEntry entry)
Definition: __init__.py:125
bool async_setup(HomeAssistant hass, ConfigType config)
Definition: __init__.py:60
Api _get_canary_api_instance(ConfigEntry entry)
Definition: __init__.py:141