1 """Support for Minut Point."""
4 from dataclasses
import dataclass
5 from http
import HTTPStatus
8 from aiohttp
import ClientError, ClientResponseError, web
9 from pypoint
import PointSession
10 import voluptuous
as vol
15 async_import_client_credential,
28 config_entry_oauth2_flow,
29 config_validation
as cv,
47 _LOGGER = logging.getLogger(__name__)
49 PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR]
51 type PointConfigEntry = ConfigEntry[PointData]
53 CONFIG_SCHEMA = vol.Schema(
57 vol.Required(CONF_CLIENT_ID): cv.string,
58 vol.Required(CONF_CLIENT_SECRET): cv.string,
62 extra=vol.ALLOW_EXTRA,
66 async
def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
67 """Set up the Minut Point component."""
68 if DOMAIN
not in config:
76 f
"deprecated_yaml_{DOMAIN}",
77 breaks_in_ha_version=
"2025.4.0",
80 severity=IssueSeverity.WARNING,
81 translation_key=
"deprecated_yaml",
82 translation_placeholders={
84 "integration_title":
"Point",
88 if not hass.config_entries.async_entries(DOMAIN):
94 conf[CONF_CLIENT_SECRET],
98 hass.async_create_task(
99 hass.config_entries.flow.async_init(
100 DOMAIN, context={
"source": SOURCE_IMPORT}, data=conf
108 """Set up Minut Point from a config entry."""
110 if "auth_implementation" not in entry.data:
114 await config_entry_oauth2_flow.async_get_config_entry_implementation(
118 session = config_entry_oauth2_flow.OAuth2Session(hass, entry, implementation)
120 aiohttp_client.async_get_clientsession(hass), session
124 await auth.async_get_access_token()
125 except ClientResponseError
as err:
126 if err.status
in {HTTPStatus.UNAUTHORIZED, HTTPStatus.FORBIDDEN}:
127 raise ConfigEntryAuthFailed
from err
128 raise ConfigEntryNotReady
from err
129 except ClientError
as err:
130 raise ConfigEntryNotReady
from err
132 point_session = PointSession(auth)
135 hass.async_create_task(client.update())
139 await hass.config_entries.async_forward_entry_setups(
140 entry, [*PLATFORMS, Platform.ALARM_CONTROL_PANEL]
147 hass: HomeAssistant, entry: PointConfigEntry, session: PointSession
149 """Set up a webhook to handle binary sensor events."""
150 if CONF_WEBHOOK_ID
not in entry.data:
151 webhook_id = webhook.async_generate_id()
152 webhook_url = webhook.async_generate_url(hass, webhook_id)
153 _LOGGER.debug(
"Registering new webhook at: %s", webhook_url)
155 hass.config_entries.async_update_entry(
159 CONF_WEBHOOK_ID: webhook_id,
160 CONF_WEBHOOK_URL: webhook_url,
164 await session.update_webhook(
165 webhook.async_generate_url(hass, entry.data[CONF_WEBHOOK_ID]),
166 entry.data[CONF_WEBHOOK_ID],
169 webhook.async_register(
170 hass, DOMAIN,
"Point", entry.data[CONF_WEBHOOK_ID], handle_webhook
175 """Unload a config entry."""
176 if unload_ok := await hass.config_entries.async_unload_platforms(
177 entry, [*PLATFORMS, Platform.ALARM_CONTROL_PANEL]
179 session: PointSession = entry.runtime_data.client
180 if CONF_WEBHOOK_ID
in entry.data:
181 webhook.async_unregister(hass, entry.data[CONF_WEBHOOK_ID])
182 await session.remove_webhook()
187 hass: HomeAssistant, webhook_id: str, request: web.Request
189 """Handle webhook callback."""
191 data = await request.json()
192 _LOGGER.debug(
"Webhook %s: %s", webhook_id, data)
196 if isinstance(data, dict):
197 data[
"webhook_id"] = webhook_id
199 hass.bus.async_fire(EVENT_RECEIVED, data)
203 """Get the latest data and update the states."""
206 self, hass: HomeAssistant, config_entry: ConfigEntry, session: PointSession
208 """Initialize the Minut data object."""
209 self._known_devices: set[str] = set()
210 self._known_homes: set[str] = set()
219 """Periodically poll the cloud for current state."""
220 await self.
_sync_sync()
223 """Update local list of devices."""
226 _LOGGER.warning(
"Device is unavailable")
231 for home_id
in self.
_client_client.homes:
232 if home_id
not in self._known_homes:
235 POINT_DISCOVERY_NEW.format(Platform.ALARM_CONTROL_PANEL),
238 self._known_homes.
add(home_id)
239 for device
in self.
_client_client.devices:
240 if device.device_id
not in self._known_devices:
241 for platform
in PLATFORMS:
244 POINT_DISCOVERY_NEW.format(platform),
247 self._known_devices.
add(device.device_id)
251 """Return device representation."""
255 """Return device availability."""
258 return device_id
in self.
_client_client.device_ids
261 """Remove the session webhook."""
266 """Return known homes."""
267 return self.
_client_client.homes
270 """Send alarm disarm command."""
271 return await self.
_client_client.alarm_disarm(home_id)
274 """Send alarm arm command."""
275 return await self.
_client_client.alarm_arm(home_id)
282 client: MinutPointClient
283 entry_lock: asyncio.Lock = asyncio.Lock()
def is_available(self, device_id)
def async_alarm_disarm(self, home_id)
None __init__(self, HomeAssistant hass, ConfigEntry config_entry, PointSession session)
def async_alarm_arm(self, home_id)
def device(self, device_id)
None async_import_client_credential(HomeAssistant hass, str domain, ClientCredential credential, str|None auth_domain=None)
bool add(self, _T matcher)
None async_create_issue(HomeAssistant hass, str entry_id)
bool async_setup(HomeAssistant hass, ConfigType config)
None handle_webhook(HomeAssistant hass, str webhook_id, web.Request request)
bool async_unload_entry(HomeAssistant hass, PointConfigEntry entry)
bool async_setup_entry(HomeAssistant hass, PointConfigEntry entry)
None async_setup_webhook(HomeAssistant hass, PointConfigEntry entry, PointSession session)
None async_dispatcher_send(HomeAssistant hass, str signal, *Any args)
CALLBACK_TYPE async_track_time_interval(HomeAssistant hass, Callable[[datetime], Coroutine[Any, Any, None]|None] action, timedelta interval, *str|None name=None, bool|None cancel_on_shutdown=None)