Improve code quality alarm_control_panel in yale_smart_alarm (#63672)
* Code quality yale_smart_alarm * Raise error on arming * Raise error if not possible to arm/disarm * Type checking and settings properties * Fix direct write statepull/64024/head
parent
f4f1ea4068
commit
4b6e196606
|
@ -1,7 +1,15 @@
|
||||||
"""Support for Yale Alarm."""
|
"""Support for Yale Alarm."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
from yalesmartalarmclient.const import (
|
||||||
|
YALE_STATE_ARM_FULL,
|
||||||
|
YALE_STATE_ARM_PARTIAL,
|
||||||
|
YALE_STATE_DISARM,
|
||||||
|
)
|
||||||
|
from yalesmartalarmclient.exceptions import AuthenticationError, UnknownError
|
||||||
|
|
||||||
from homeassistant.components.alarm_control_panel import (
|
from homeassistant.components.alarm_control_panel import (
|
||||||
PLATFORM_SCHEMA as PARENT_PLATFORM_SCHEMA,
|
PLATFORM_SCHEMA as PARENT_PLATFORM_SCHEMA,
|
||||||
|
@ -14,10 +22,11 @@ from homeassistant.components.alarm_control_panel.const import (
|
||||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
||||||
from homeassistant.const import CONF_NAME, CONF_PASSWORD, CONF_USERNAME
|
from homeassistant.const import CONF_NAME, CONF_PASSWORD, CONF_USERNAME
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity import DeviceInfo
|
from homeassistant.helpers.entity import DeviceInfo
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType, StateType
|
||||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
|
@ -75,51 +84,108 @@ async def async_setup_entry(
|
||||||
class YaleAlarmDevice(CoordinatorEntity, AlarmControlPanelEntity):
|
class YaleAlarmDevice(CoordinatorEntity, AlarmControlPanelEntity):
|
||||||
"""Represent a Yale Smart Alarm."""
|
"""Represent a Yale Smart Alarm."""
|
||||||
|
|
||||||
|
_attr_code_arm_required = False
|
||||||
|
_attr_supported_features = SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY
|
||||||
|
|
||||||
def __init__(self, coordinator: YaleDataUpdateCoordinator) -> None:
|
def __init__(self, coordinator: YaleDataUpdateCoordinator) -> None:
|
||||||
"""Initialize the Yale Alarm Device."""
|
"""Initialize the Yale Alarm Device."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self._attr_name: str = coordinator.entry.data[CONF_NAME]
|
self._coordinator = coordinator
|
||||||
|
self._attr_name = coordinator.entry.data[CONF_NAME]
|
||||||
self._attr_unique_id = coordinator.entry.entry_id
|
self._attr_unique_id = coordinator.entry.entry_id
|
||||||
self._identifier: str = coordinator.entry.data[CONF_USERNAME]
|
self._attr_device_info = DeviceInfo(
|
||||||
|
identifiers={(DOMAIN, coordinator.entry.data[CONF_USERNAME])},
|
||||||
@property
|
|
||||||
def device_info(self) -> DeviceInfo:
|
|
||||||
"""Return device information about this entity."""
|
|
||||||
return DeviceInfo(
|
|
||||||
identifiers={(DOMAIN, self._identifier)},
|
|
||||||
manufacturer=MANUFACTURER,
|
manufacturer=MANUFACTURER,
|
||||||
model=MODEL,
|
model=MODEL,
|
||||||
name=str(self.name),
|
name=self._attr_name,
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
async def async_alarm_disarm(self, code=None) -> None:
|
||||||
def state(self):
|
|
||||||
"""Return the state of the device."""
|
|
||||||
return STATE_MAP.get(self.coordinator.data["alarm"])
|
|
||||||
|
|
||||||
@property
|
|
||||||
def available(self):
|
|
||||||
"""Return if entity is available."""
|
|
||||||
return STATE_MAP.get(self.coordinator.data["alarm"]) is not None
|
|
||||||
|
|
||||||
@property
|
|
||||||
def code_arm_required(self):
|
|
||||||
"""Whether the code is required for arm actions."""
|
|
||||||
return False
|
|
||||||
|
|
||||||
@property
|
|
||||||
def supported_features(self) -> int:
|
|
||||||
"""Return the list of supported features."""
|
|
||||||
return SUPPORT_ALARM_ARM_HOME | SUPPORT_ALARM_ARM_AWAY
|
|
||||||
|
|
||||||
def alarm_disarm(self, code=None):
|
|
||||||
"""Send disarm command."""
|
"""Send disarm command."""
|
||||||
self.coordinator.yale.disarm()
|
if TYPE_CHECKING:
|
||||||
|
assert self._coordinator.yale, "Connection to API is missing"
|
||||||
|
|
||||||
def alarm_arm_home(self, code=None):
|
try:
|
||||||
|
alarm_state = await self.hass.async_add_executor_job(
|
||||||
|
self._coordinator.yale.disarm
|
||||||
|
)
|
||||||
|
except (
|
||||||
|
AuthenticationError,
|
||||||
|
ConnectionError,
|
||||||
|
TimeoutError,
|
||||||
|
UnknownError,
|
||||||
|
) as error:
|
||||||
|
raise HomeAssistantError(
|
||||||
|
f"Could not verify disarmed for {self._attr_name}: {error}"
|
||||||
|
) from error
|
||||||
|
|
||||||
|
LOGGER.debug("Alarm disarmed: %s", alarm_state)
|
||||||
|
if alarm_state:
|
||||||
|
self.coordinator.data["alarm"] = YALE_STATE_DISARM
|
||||||
|
self.async_write_ha_state()
|
||||||
|
return
|
||||||
|
raise HomeAssistantError("Could not disarm, check system ready for disarming.")
|
||||||
|
|
||||||
|
async def async_alarm_arm_home(self, code=None) -> None:
|
||||||
"""Send arm home command."""
|
"""Send arm home command."""
|
||||||
self.coordinator.yale.arm_partial()
|
if TYPE_CHECKING:
|
||||||
|
assert self._coordinator.yale, "Connection to API is missing"
|
||||||
|
|
||||||
def alarm_arm_away(self, code=None):
|
try:
|
||||||
|
alarm_state = await self.hass.async_add_executor_job(
|
||||||
|
self._coordinator.yale.arm_partial
|
||||||
|
)
|
||||||
|
except (
|
||||||
|
AuthenticationError,
|
||||||
|
ConnectionError,
|
||||||
|
TimeoutError,
|
||||||
|
UnknownError,
|
||||||
|
) as error:
|
||||||
|
raise HomeAssistantError(
|
||||||
|
f"Could not verify armed home for {self._attr_name}: {error}"
|
||||||
|
) from error
|
||||||
|
|
||||||
|
LOGGER.debug("Alarm armed home: %s", alarm_state)
|
||||||
|
if alarm_state:
|
||||||
|
self.coordinator.data["alarm"] = YALE_STATE_ARM_PARTIAL
|
||||||
|
self.async_write_ha_state()
|
||||||
|
return
|
||||||
|
raise HomeAssistantError("Could not arm home, check system ready for arming.")
|
||||||
|
|
||||||
|
async def async_alarm_arm_away(self, code=None) -> None:
|
||||||
"""Send arm away command."""
|
"""Send arm away command."""
|
||||||
self.coordinator.yale.arm_full()
|
if TYPE_CHECKING:
|
||||||
|
assert self._coordinator.yale, "Connection to API is missing"
|
||||||
|
|
||||||
|
try:
|
||||||
|
alarm_state = await self.hass.async_add_executor_job(
|
||||||
|
self._coordinator.yale.arm_full
|
||||||
|
)
|
||||||
|
except (
|
||||||
|
AuthenticationError,
|
||||||
|
ConnectionError,
|
||||||
|
TimeoutError,
|
||||||
|
UnknownError,
|
||||||
|
) as error:
|
||||||
|
raise HomeAssistantError(
|
||||||
|
f"Could not verify armed away for {self._attr_name}: {error}"
|
||||||
|
) from error
|
||||||
|
|
||||||
|
LOGGER.debug("Alarm armed away: %s", alarm_state)
|
||||||
|
if alarm_state:
|
||||||
|
self.coordinator.data["alarm"] = YALE_STATE_ARM_FULL
|
||||||
|
self.async_write_ha_state()
|
||||||
|
return
|
||||||
|
raise HomeAssistantError("Could not arm away, check system ready for arming.")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def available(self) -> bool:
|
||||||
|
"""Return True if alarm is available."""
|
||||||
|
if STATE_MAP.get(self.coordinator.data["alarm"]) is None:
|
||||||
|
return False
|
||||||
|
return super().available
|
||||||
|
|
||||||
|
@property
|
||||||
|
def state(self) -> StateType:
|
||||||
|
"""Return the state of the alarm."""
|
||||||
|
return STATE_MAP.get(self.coordinator.data["alarm"])
|
||||||
|
|
Loading…
Reference in New Issue