141 lines
3.8 KiB
Python
141 lines
3.8 KiB
Python
"""Implement the Yandex Smart Home base device property."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from abc import abstractmethod
|
|
from typing import TYPE_CHECKING, Any, Protocol, Self, runtime_checkable
|
|
|
|
from homeassistant.const import ATTR_DEVICE_CLASS
|
|
from homeassistant.core import HomeAssistant, State
|
|
|
|
from .helpers import ListRegistry
|
|
from .schema import (
|
|
PropertyDescription,
|
|
PropertyInstance,
|
|
PropertyInstanceState,
|
|
PropertyInstanceStateValue,
|
|
PropertyParameters,
|
|
PropertyType,
|
|
)
|
|
|
|
if TYPE_CHECKING:
|
|
from .entry_data import ConfigEntryData
|
|
|
|
|
|
@runtime_checkable
|
|
class Property(Protocol):
|
|
"""Base class for a device property."""
|
|
|
|
device_id: str
|
|
type: PropertyType
|
|
instance: PropertyInstance
|
|
|
|
_hass: HomeAssistant
|
|
_entry_data: ConfigEntryData
|
|
|
|
@property
|
|
@abstractmethod
|
|
def supported(self) -> bool:
|
|
"""Test if the property is supported."""
|
|
...
|
|
|
|
@property
|
|
def retrievable(self) -> bool:
|
|
"""Test if the property can return the current value."""
|
|
return True
|
|
|
|
@property
|
|
def reportable(self) -> bool:
|
|
"""Test if the property can report value changes."""
|
|
return self._entry_data.is_reporting_states
|
|
|
|
@property
|
|
def heartbeat_report(self) -> bool:
|
|
"""Test if property value should be reported on startup and periodically."""
|
|
return True
|
|
|
|
@property
|
|
def time_sensitive(self) -> bool:
|
|
"""Test if value changes should be reported immediately."""
|
|
return False
|
|
|
|
@property
|
|
@abstractmethod
|
|
def parameters(self) -> PropertyParameters:
|
|
"""Return parameters for a devices list request."""
|
|
...
|
|
|
|
@abstractmethod
|
|
def get_description(self) -> PropertyDescription:
|
|
"""Return a description for a device list request."""
|
|
...
|
|
|
|
@abstractmethod
|
|
def get_value(self) -> Any:
|
|
"""Return the current property value."""
|
|
...
|
|
|
|
def get_instance_state(self) -> PropertyInstanceState | None:
|
|
"""Return a state for a state query request."""
|
|
if (value := self.get_value()) is not None:
|
|
return PropertyInstanceState(
|
|
type=self.type, state=PropertyInstanceStateValue(instance=self.instance, value=value)
|
|
)
|
|
|
|
return None
|
|
|
|
@abstractmethod
|
|
def check_value_change(self, other: Self | None) -> bool:
|
|
"""Test if the property value differs from other property."""
|
|
...
|
|
|
|
def __str__(self) -> str:
|
|
"""Return string representation."""
|
|
return f"instance {self.instance} of {self.type.short} property of {self.device_id}"
|
|
|
|
def __repr__(self) -> str:
|
|
"""Return the representation."""
|
|
return (
|
|
f"<{self.__class__.__name__}"
|
|
f" device_id={self.device_id }"
|
|
f" type={self.type}"
|
|
f" instance={self.instance}"
|
|
f">"
|
|
)
|
|
|
|
def __eq__(self, other: Any) -> bool:
|
|
"""Compare properties."""
|
|
return bool(
|
|
isinstance(other, Property)
|
|
and self.type == other.type
|
|
and self.instance == other.instance
|
|
and self.device_id == other.device_id
|
|
)
|
|
|
|
|
|
@runtime_checkable
|
|
class StateProperty(Property, Protocol):
|
|
"""Base class for a device property based on the state."""
|
|
|
|
state: State
|
|
device_id: str
|
|
|
|
_hass: HomeAssistant
|
|
_entry_data: ConfigEntryData
|
|
|
|
def __init__(self, hass: HomeAssistant, entry_data: ConfigEntryData, device_id: str, state: State):
|
|
"""Initialize a property for the state."""
|
|
self._hass = hass
|
|
self._entry_data = entry_data
|
|
|
|
self.state = state
|
|
self.device_id = device_id
|
|
|
|
@property
|
|
def _state_device_class(self) -> str | None:
|
|
"""Return state device class."""
|
|
return self.state.attributes.get(ATTR_DEVICE_CLASS)
|
|
|
|
|
|
STATE_PROPERTIES_REGISTRY = ListRegistry[type[StateProperty]]()
|