178 lines
5.4 KiB
Python
178 lines
5.4 KiB
Python
"""Support for Verisure devices."""
|
|
from __future__ import annotations
|
|
|
|
import asyncio
|
|
import os
|
|
from typing import Any
|
|
|
|
import voluptuous as vol
|
|
|
|
from homeassistant.components.alarm_control_panel import (
|
|
DOMAIN as ALARM_CONTROL_PANEL_DOMAIN,
|
|
)
|
|
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
|
|
from homeassistant.components.camera import DOMAIN as CAMERA_DOMAIN
|
|
from homeassistant.components.lock import DOMAIN as LOCK_DOMAIN
|
|
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
|
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
|
from homeassistant.config_entries import SOURCE_IMPORT, SOURCE_REAUTH, ConfigEntry
|
|
from homeassistant.const import (
|
|
CONF_EMAIL,
|
|
CONF_PASSWORD,
|
|
CONF_USERNAME,
|
|
EVENT_HOMEASSISTANT_STOP,
|
|
)
|
|
from homeassistant.core import HomeAssistant
|
|
from homeassistant.exceptions import ConfigEntryNotReady
|
|
import homeassistant.helpers.config_validation as cv
|
|
from homeassistant.helpers.storage import STORAGE_DIR
|
|
|
|
from .const import (
|
|
CONF_CODE_DIGITS,
|
|
CONF_DEFAULT_LOCK_CODE,
|
|
CONF_GIID,
|
|
CONF_LOCK_CODE_DIGITS,
|
|
CONF_LOCK_DEFAULT_CODE,
|
|
DEFAULT_LOCK_CODE_DIGITS,
|
|
DOMAIN,
|
|
)
|
|
from .coordinator import VerisureDataUpdateCoordinator
|
|
|
|
PLATFORMS = [
|
|
ALARM_CONTROL_PANEL_DOMAIN,
|
|
BINARY_SENSOR_DOMAIN,
|
|
CAMERA_DOMAIN,
|
|
LOCK_DOMAIN,
|
|
SENSOR_DOMAIN,
|
|
SWITCH_DOMAIN,
|
|
]
|
|
|
|
CONFIG_SCHEMA = vol.Schema(
|
|
vol.All(
|
|
cv.deprecated(DOMAIN),
|
|
{
|
|
DOMAIN: vol.Schema(
|
|
{
|
|
vol.Required(CONF_PASSWORD): cv.string,
|
|
vol.Required(CONF_USERNAME): cv.string,
|
|
vol.Optional(CONF_CODE_DIGITS): cv.positive_int,
|
|
vol.Optional(CONF_GIID): cv.string,
|
|
vol.Optional(CONF_DEFAULT_LOCK_CODE): cv.string,
|
|
},
|
|
extra=vol.ALLOW_EXTRA,
|
|
)
|
|
},
|
|
),
|
|
extra=vol.ALLOW_EXTRA,
|
|
)
|
|
|
|
|
|
async def async_setup(hass: HomeAssistant, config: dict[str, Any]) -> bool:
|
|
"""Set up the Verisure integration."""
|
|
if DOMAIN in config:
|
|
hass.async_create_task(
|
|
hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": SOURCE_IMPORT},
|
|
data={
|
|
CONF_EMAIL: config[DOMAIN][CONF_USERNAME],
|
|
CONF_PASSWORD: config[DOMAIN][CONF_PASSWORD],
|
|
CONF_GIID: config[DOMAIN].get(CONF_GIID),
|
|
CONF_LOCK_CODE_DIGITS: config[DOMAIN].get(CONF_CODE_DIGITS),
|
|
CONF_LOCK_DEFAULT_CODE: config[DOMAIN].get(CONF_LOCK_DEFAULT_CODE),
|
|
},
|
|
)
|
|
)
|
|
|
|
return True
|
|
|
|
|
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|
"""Set up Verisure from a config entry."""
|
|
# Migrate old YAML settings (hidden in the config entry),
|
|
# to config entry options. Can be removed after YAML support is gone.
|
|
if CONF_LOCK_CODE_DIGITS in entry.data or CONF_DEFAULT_LOCK_CODE in entry.data:
|
|
options = entry.options.copy()
|
|
|
|
if (
|
|
CONF_LOCK_CODE_DIGITS in entry.data
|
|
and CONF_LOCK_CODE_DIGITS not in entry.options
|
|
and entry.data[CONF_LOCK_CODE_DIGITS] != DEFAULT_LOCK_CODE_DIGITS
|
|
):
|
|
options.update(
|
|
{
|
|
CONF_LOCK_CODE_DIGITS: entry.data[CONF_LOCK_CODE_DIGITS],
|
|
}
|
|
)
|
|
|
|
if (
|
|
CONF_DEFAULT_LOCK_CODE in entry.data
|
|
and CONF_DEFAULT_LOCK_CODE not in entry.options
|
|
):
|
|
options.update(
|
|
{
|
|
CONF_DEFAULT_LOCK_CODE: entry.data[CONF_DEFAULT_LOCK_CODE],
|
|
}
|
|
)
|
|
|
|
data = entry.data.copy()
|
|
data.pop(CONF_LOCK_CODE_DIGITS, None)
|
|
data.pop(CONF_DEFAULT_LOCK_CODE, None)
|
|
hass.config_entries.async_update_entry(entry, data=data, options=options)
|
|
|
|
# Continue as normal...
|
|
coordinator = VerisureDataUpdateCoordinator(hass, entry=entry)
|
|
|
|
if not await coordinator.async_login():
|
|
await hass.config_entries.flow.async_init(
|
|
DOMAIN,
|
|
context={"source": SOURCE_REAUTH},
|
|
data={"entry": entry},
|
|
)
|
|
return False
|
|
|
|
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, coordinator.async_logout)
|
|
|
|
await coordinator.async_refresh()
|
|
if not coordinator.last_update_success:
|
|
raise ConfigEntryNotReady
|
|
|
|
hass.data.setdefault(DOMAIN, {})
|
|
hass.data[DOMAIN][entry.entry_id] = coordinator
|
|
|
|
# Set up all platforms for this device/entry.
|
|
for platform in PLATFORMS:
|
|
hass.async_create_task(
|
|
hass.config_entries.async_forward_entry_setup(entry, platform)
|
|
)
|
|
|
|
return True
|
|
|
|
|
|
async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|
"""Unload Verisure config entry."""
|
|
unload_ok = all(
|
|
await asyncio.gather(
|
|
*(
|
|
hass.config_entries.async_forward_entry_unload(entry, platform)
|
|
for platform in PLATFORMS
|
|
)
|
|
)
|
|
)
|
|
|
|
if not unload_ok:
|
|
return False
|
|
|
|
cookie_file = hass.config.path(STORAGE_DIR, f"verisure_{entry.entry_id}")
|
|
try:
|
|
await hass.async_add_executor_job(os.unlink, cookie_file)
|
|
except FileNotFoundError:
|
|
pass
|
|
|
|
del hass.data[DOMAIN][entry.entry_id]
|
|
|
|
if not hass.data[DOMAIN]:
|
|
del hass.data[DOMAIN]
|
|
|
|
return True
|