From f7229319207b2de4d2d5c5eae9467aa37e3e8533 Mon Sep 17 00:00:00 2001 From: Mick Vleeshouwer Date: Thu, 23 Dec 2021 15:28:01 -0800 Subject: [PATCH] Add lock entity to Overkiz integration (#62713) --- .coveragerc | 1 + homeassistant/components/overkiz/__init__.py | 14 +++++ homeassistant/components/overkiz/const.py | 6 +++ homeassistant/components/overkiz/lock.py | 52 +++++++++++++++++++ homeassistant/components/overkiz/sensor.py | 2 +- .../components/overkiz/translations/en.json | 8 ++- 6 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 homeassistant/components/overkiz/lock.py diff --git a/.coveragerc b/.coveragerc index 24f01b0c463..275a65fab95 100644 --- a/.coveragerc +++ b/.coveragerc @@ -806,6 +806,7 @@ omit = homeassistant/components/overkiz/coordinator.py homeassistant/components/overkiz/entity.py homeassistant/components/overkiz/executor.py + homeassistant/components/overkiz/lock.py homeassistant/components/overkiz/sensor.py homeassistant/components/ovo_energy/__init__.py homeassistant/components/ovo_energy/const.py diff --git a/homeassistant/components/overkiz/__init__.py b/homeassistant/components/overkiz/__init__.py index 77c02daf2a6..c60a3104839 100644 --- a/homeassistant/components/overkiz/__init__.py +++ b/homeassistant/components/overkiz/__init__.py @@ -1,4 +1,7 @@ """The Overkiz (by Somfy) integration.""" +from __future__ import annotations + +from collections import defaultdict from dataclasses import dataclass import logging @@ -10,6 +13,7 @@ from pyoverkiz.exceptions import ( MaintenanceException, TooManyRequestsException, ) +from pyoverkiz.models import Device from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_PASSWORD, CONF_USERNAME @@ -21,6 +25,7 @@ from homeassistant.helpers.aiohttp_client import async_create_clientsession from .const import ( CONF_HUB, DOMAIN, + OVERKIZ_DEVICE_TO_PLATFORM, PLATFORMS, UPDATE_INTERVAL, UPDATE_INTERVAL_ALL_ASSUMED_STATE, @@ -35,6 +40,7 @@ class HomeAssistantOverkizData: """Overkiz data stored in the Home Assistant data object.""" coordinator: OverkizDataUpdateCoordinator + platforms: dict[str, Device] async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: @@ -85,8 +91,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: ) coordinator.update_interval = UPDATE_INTERVAL_ALL_ASSUMED_STATE + platforms: dict[str, Device] = defaultdict(list) + hass.data.setdefault(DOMAIN, {})[entry.entry_id] = HomeAssistantOverkizData( coordinator=coordinator, + platforms=platforms, ) # Map Overkiz device to Home Assistant platform @@ -96,6 +105,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: device, ) + if platform := OVERKIZ_DEVICE_TO_PLATFORM.get( + device.widget + ) or OVERKIZ_DEVICE_TO_PLATFORM.get(device.ui_class): + platforms[platform].append(device) + hass.config_entries.async_setup_platforms(entry, PLATFORMS) device_registry = await dr.async_get_registry(hass) diff --git a/homeassistant/components/overkiz/const.py b/homeassistant/components/overkiz/const.py index ff5dea13c65..95919a18265 100644 --- a/homeassistant/components/overkiz/const.py +++ b/homeassistant/components/overkiz/const.py @@ -18,6 +18,7 @@ UPDATE_INTERVAL: Final = timedelta(seconds=30) UPDATE_INTERVAL_ALL_ASSUMED_STATE: Final = timedelta(minutes=60) PLATFORMS: list[Platform] = [ + Platform.LOCK, Platform.SENSOR, ] @@ -25,3 +26,8 @@ IGNORED_OVERKIZ_DEVICES: list[UIClass | UIWidget] = [ UIClass.PROTOCOL_GATEWAY, UIClass.POD, ] + +# Used to map the Somfy widget and ui_class to the Home Assistant platform +OVERKIZ_DEVICE_TO_PLATFORM: dict[UIClass | UIWidget, Platform] = { + UIClass.DOOR_LOCK: Platform.LOCK, +} diff --git a/homeassistant/components/overkiz/lock.py b/homeassistant/components/overkiz/lock.py new file mode 100644 index 00000000000..89a091751d9 --- /dev/null +++ b/homeassistant/components/overkiz/lock.py @@ -0,0 +1,52 @@ +"""Support for Overkiz locks.""" +from __future__ import annotations + +from typing import Any + +from pyoverkiz.enums import OverkizCommand, OverkizCommandParam, OverkizState + +from homeassistant.components.lock import LockEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.const import Platform +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddEntitiesCallback + +from . import HomeAssistantOverkizData +from .const import DOMAIN +from .entity import OverkizEntity + + +async def async_setup_entry( + hass: HomeAssistant, + entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +): + """Set up the Overkiz locks from a config entry.""" + data: HomeAssistantOverkizData = hass.data[DOMAIN][entry.entry_id] + + entities: list[OverkizLock] = [ + OverkizLock(device.device_url, data.coordinator) + for device in data.platforms[Platform.LOCK] + ] + + async_add_entities(entities) + + +class OverkizLock(OverkizEntity, LockEntity): + """Representation of an Overkiz Lock.""" + + async def async_lock(self, **_: Any) -> None: + """Lock method.""" + await self.executor.async_execute_command(OverkizCommand.LOCK) + + async def async_unlock(self, **_: Any) -> None: + """Unlock method.""" + await self.executor.async_execute_command(OverkizCommand.UNLOCK) + + @property + def is_locked(self) -> bool | None: + """Return a boolean for the state of the lock.""" + return ( + self.executor.select_state(OverkizState.CORE_LOCKED_UNLOCKED) + == OverkizCommandParam.LOCKED + ) diff --git a/homeassistant/components/overkiz/sensor.py b/homeassistant/components/overkiz/sensor.py index 2f933055507..a00587328b8 100644 --- a/homeassistant/components/overkiz/sensor.py +++ b/homeassistant/components/overkiz/sensor.py @@ -3,7 +3,6 @@ from __future__ import annotations from pyoverkiz.enums import OverkizAttribute, OverkizState, UIWidget -from homeassistant.components.overkiz import HomeAssistantOverkizData from homeassistant.components.sensor import ( SensorDeviceClass, SensorEntity, @@ -26,6 +25,7 @@ from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import DeviceInfo, EntityCategory from homeassistant.helpers.entity_platform import AddEntitiesCallback +from . import HomeAssistantOverkizData from .const import DOMAIN, IGNORED_OVERKIZ_DEVICES from .coordinator import OverkizDataUpdateCoordinator from .entity import OverkizDescriptiveEntity, OverkizEntity, OverkizSensorDescription diff --git a/homeassistant/components/overkiz/translations/en.json b/homeassistant/components/overkiz/translations/en.json index f15fe84c3ed..fe46f3fe9fb 100644 --- a/homeassistant/components/overkiz/translations/en.json +++ b/homeassistant/components/overkiz/translations/en.json @@ -1,20 +1,24 @@ { "config": { "abort": { - "already_configured": "Device is already configured" + "already_configured": "Account is already configured" }, "error": { "cannot_connect": "Failed to connect", "invalid_auth": "Invalid authentication", + "server_in_maintenance": "Server is down for maintenance", + "too_many_requests": "Too many requests, try again later.", "unknown": "Unexpected error" }, "step": { "user": { "data": { "host": "Host", + "hub": "Hub", "password": "Password", "username": "Username" - } + }, + "description": "The Overkiz platform is used by various vendors like Somfy (Connexoon / TaHoma), Hitachi (Hi Kumo), Rexel (Energeasy Connect) and Atlantic (Cozytouch). Enter your application credentials and select your hub." } } }