python
This commit is contained in:
133
custom_components/yandex_station/core/entity.py
Normal file
133
custom_components/yandex_station/core/entity.py
Normal file
@@ -0,0 +1,133 @@
|
||||
import logging
|
||||
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.entity import DeviceInfo, Entity
|
||||
|
||||
from .const import DOMAIN
|
||||
from .yandex_quasar import YandexQuasar
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def extract_instance(item: dict) -> str | None:
|
||||
if item["type"] == "devices.capabilities.on_off":
|
||||
return "on"
|
||||
if item["type"] == "devices.capabilities.lock":
|
||||
return "lock"
|
||||
if item["type"] == "devices.capabilities.zigbee_node":
|
||||
return "zigbee"
|
||||
return item["parameters"].get("instance")
|
||||
|
||||
|
||||
def extract_parameters(items: list[dict]) -> dict:
|
||||
result = {}
|
||||
for item in items:
|
||||
# skip none (unknown) instances
|
||||
if instance := extract_instance(item):
|
||||
result[instance] = {"retrievable": item["retrievable"], **item["parameters"]}
|
||||
return result
|
||||
|
||||
|
||||
def extract_state(items: list[dict]) -> dict:
|
||||
result = {}
|
||||
for item in items:
|
||||
if instance := extract_instance(item):
|
||||
value = item["state"]["value"] if item["state"] else None
|
||||
result[instance] = value
|
||||
return result
|
||||
|
||||
|
||||
class YandexEntity(Entity):
|
||||
def __init__(self, quasar: YandexQuasar, device: dict, config: dict = None):
|
||||
self.quasar = quasar
|
||||
self.device = device
|
||||
self.config = config
|
||||
|
||||
# "online", "unknown" or key not exist
|
||||
self._attr_available = device.get("state") != "offline"
|
||||
self._attr_name = device["name"]
|
||||
self._attr_should_poll = False
|
||||
self._attr_unique_id = device["id"].replace("-", "")
|
||||
|
||||
device_id = i["device_id"] if (i := device.get("quasar_info")) else device["id"]
|
||||
|
||||
self._attr_device_info: DeviceInfo = DeviceInfo(
|
||||
identifiers={(DOMAIN, device_id)},
|
||||
name=self.device["name"],
|
||||
suggested_area=self.device.get("room_name"),
|
||||
)
|
||||
|
||||
if device_info := device.get("parameters", {}).get("device_info", {}):
|
||||
for key in ("manufacturer", "model", "sw_version", "hw_version"):
|
||||
if value := device_info.get(key):
|
||||
self._attr_device_info[key] = value
|
||||
|
||||
try:
|
||||
self.internal_init(
|
||||
extract_parameters(device["capabilities"]),
|
||||
extract_parameters(device["properties"]),
|
||||
)
|
||||
self.internal_update(
|
||||
extract_state(device["capabilities"]),
|
||||
extract_state(device["properties"]),
|
||||
)
|
||||
except Exception as e:
|
||||
_LOGGER.error("Device init failed: %s", repr(e))
|
||||
|
||||
self.quasar.subscribe_update(device["id"], self.on_update)
|
||||
|
||||
def on_update(self, device: dict):
|
||||
self._attr_available = device["state"] in ("online", "unknown")
|
||||
|
||||
self.internal_update(
|
||||
extract_state(device["capabilities"]) if "capabilities" in device else {},
|
||||
extract_state(device["properties"]) if "properties" in device else {},
|
||||
)
|
||||
|
||||
if self.hass and self.entity_id:
|
||||
self._async_write_ha_state()
|
||||
|
||||
def internal_init(self, capabilities: dict, properties: dict):
|
||||
"""Will be called on Entity init. Capabilities and properties will have all
|
||||
variants.
|
||||
"""
|
||||
pass
|
||||
|
||||
def internal_update(self, capabilities: dict, properties: dict):
|
||||
"""Will be called on Entity init and every data update. Variant
|
||||
- instance with some value (str, float, dict)
|
||||
- instance with null value
|
||||
- no instance (if it not upated)
|
||||
"""
|
||||
pass
|
||||
|
||||
async def async_update(self):
|
||||
device = await self.quasar.get_device(self.device)
|
||||
self.quasar.dispatch_update(device["id"], device)
|
||||
|
||||
async def device_action(self, instance: str, value, relative=False):
|
||||
try:
|
||||
await self.quasar.device_action(self.device, instance, value, relative)
|
||||
except Exception as e:
|
||||
raise HomeAssistantError(f"Device action failed: {repr(e)}")
|
||||
|
||||
async def device_actions(self, **kwargs):
|
||||
try:
|
||||
await self.quasar.device_actions(self.device, **kwargs)
|
||||
except Exception as e:
|
||||
raise HomeAssistantError(f"Device action failed: {repr(e)}")
|
||||
|
||||
async def device_color(self, **kwargs):
|
||||
try:
|
||||
await self.quasar.device_color(self.device, **kwargs)
|
||||
except Exception as e:
|
||||
raise HomeAssistantError(f"Device action failed: {repr(e)}")
|
||||
|
||||
|
||||
class YandexCustomEntity(YandexEntity):
|
||||
def __init__(self, quasar: YandexQuasar, device: dict, config: dict):
|
||||
self.instance = extract_instance(config)
|
||||
super().__init__(quasar, device, config)
|
||||
if name := config["parameters"].get("name"):
|
||||
self._attr_name += " " + name
|
||||
self._attr_unique_id += " " + self.instance
|
||||
Reference in New Issue
Block a user