Files
home-assistant-alt/hass/settings/custom_components/yandex_smart_home/prop_custom.py
T
2024-01-11 15:10:51 +03:00

131 lines
5.2 KiB
Python

"""Implement the Yandex Smart Home custom properties."""
from __future__ import annotations
from abc import ABC
import logging
from typing import Any
from homeassistant.components import binary_sensor, sensor
from homeassistant.const import ATTR_UNIT_OF_MEASUREMENT
from homeassistant.core import HomeAssistant, State
from . import const
from .const import (
CONF_ENTITY_PROPERTY_ATTRIBUTE,
CONF_ENTITY_PROPERTY_ENTITY,
CONF_ENTITY_PROPERTY_TYPE,
CONF_ENTITY_PROPERTY_UNIT_OF_MEASUREMENT,
ERR_DEVICE_UNREACHABLE,
EVENT_INSTANCES,
FLOAT_INSTANCES,
)
from .error import SmartHomeError
from .helpers import Config
from .prop import AbstractProperty
from .prop_event import EventProperty
from .prop_float import PRESSURE_UNITS_TO_YANDEX_UNITS, PROPERTY_FLOAT_INSTANCE_TO_UNITS, FloatProperty
_LOGGER = logging.getLogger(__name__)
class CustomEntityProperty(AbstractProperty, ABC):
def __init__(self, hass: HomeAssistant, config: Config, state: State,
property_state: State, property_config: dict[str, Any]):
self.instance = property_config[CONF_ENTITY_PROPERTY_TYPE]
self.property_config = property_config
self.property_state = property_state
super().__init__(hass, config, state)
@classmethod
def get(cls, hass: HomeAssistant, config: Config, state: State,
property_config: dict[str, Any]) -> CustomEventEntityProperty | CustomFloatEntityProperty:
property_state = state
property_entity_id = property_config.get(CONF_ENTITY_PROPERTY_ENTITY)
instance = property_config[CONF_ENTITY_PROPERTY_TYPE]
if property_entity_id:
property_state = hass.states.get(property_entity_id)
if property_state is None:
raise SmartHomeError(
ERR_DEVICE_UNREACHABLE,
f'Entity {property_entity_id} not found for {instance} instance of {state.entity_id}'
)
if property_state.domain == binary_sensor.DOMAIN:
if instance not in EVENT_INSTANCES:
raise SmartHomeError(
ERR_DEVICE_UNREACHABLE,
f'Unsupported entity {property_state.entity_id} for {instance} instance '
f'of {state.entity_id}'
)
return CustomEventEntityProperty(hass, config, state, property_state, property_config)
elif property_state.domain == sensor.DOMAIN:
if instance not in FLOAT_INSTANCES and instance in EVENT_INSTANCES:
# TODO: battery_level and water_level cannot be events for sensor domain
return CustomEventEntityProperty(hass, config, state, property_state, property_config)
return CustomFloatEntityProperty(hass, config, state, property_state, property_config)
def supported(self) -> bool:
return True
def get_value(self) -> str | float | None:
value_attribute = self.property_config.get(CONF_ENTITY_PROPERTY_ATTRIBUTE)
if value_attribute:
if value_attribute not in self.property_state.attributes:
raise SmartHomeError(
ERR_DEVICE_UNREACHABLE,
f'Attribute {value_attribute} not found in entity {self.property_state.entity_id} '
f'for {self.instance} instance of {self.state.entity_id}'
)
value = self.property_state.attributes[value_attribute]
else:
value = self.property_state.state
return value
@property
def property_entity_id(self) -> str | None:
return self.property_config.get(CONF_ENTITY_PROPERTY_ENTITY, self.property_state.entity_id)
class CustomFloatEntityProperty(CustomEntityProperty, FloatProperty):
def __init__(self, hass: HomeAssistant, config: Config, state: State,
property_state: State, property_config: dict[str, str]):
super().__init__(hass, config, state, property_state, property_config)
@property
def unit(self) -> str:
if self.instance == const.FLOAT_INSTANCE_PRESSURE:
return PRESSURE_UNITS_TO_YANDEX_UNITS[self.config.pressure_unit]
return PROPERTY_FLOAT_INSTANCE_TO_UNITS[self.instance]
def get_value(self) -> float | None:
value = super().get_value()
if self.instance in [const.FLOAT_INSTANCE_PRESSURE, const.FLOAT_INSTANCE_TVOC, const.FLOAT_INSTANCE_AMPERAGE]:
value_unit = self.property_config.get(CONF_ENTITY_PROPERTY_UNIT_OF_MEASUREMENT,
self.property_state.attributes.get(ATTR_UNIT_OF_MEASUREMENT))
return self.convert_value(value, value_unit)
return self.float_value(value)
class CustomEventEntityProperty(CustomEntityProperty, EventProperty):
report_immediately = True
def __init__(self, hass: HomeAssistant, config: Config, state: State,
property_state: State, property_config: dict[str, str]):
super().__init__(hass, config, state, property_state, property_config)
if self.instance in [const.EVENT_INSTANCE_BUTTON, const.EVENT_INSTANCE_VIBRATION]:
self.retrievable = False
def get_value(self) -> str | None:
return self.event_value(super().get_value())