90 lines
3.4 KiB
Python
90 lines
3.4 KiB
Python
"""Base entity for the Maintenance Supporter integration."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from homeassistant.helpers import device_registry as dr
|
|
from homeassistant.helpers.device_registry import DeviceInfo
|
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
|
|
|
from ..const import CONF_OBJECT, DOMAIN, GLOBAL_UNIQUE_ID
|
|
from ..coordinator import MaintenanceCoordinator
|
|
|
|
|
|
class MaintenanceEntity(CoordinatorEntity[MaintenanceCoordinator]):
|
|
"""Base class for Maintenance Supporter entities."""
|
|
|
|
_attr_has_entity_name = True
|
|
|
|
def __init__(
|
|
self,
|
|
coordinator: MaintenanceCoordinator,
|
|
task_id: str,
|
|
) -> None:
|
|
"""Initialize the base entity."""
|
|
super().__init__(coordinator)
|
|
self._task_id = task_id
|
|
self._object_data = coordinator.entry.data.get(CONF_OBJECT, {})
|
|
|
|
@property
|
|
def device_info(self) -> DeviceInfo:
|
|
"""Return device info for this maintenance object.
|
|
|
|
Three shapes (2.19, device attachment):
|
|
|
|
* ``ha_device_id`` set → attach to that EXISTING device: return only
|
|
its identifiers/connections so the registry merges us onto it — no
|
|
name/manufacturer, which would overwrite the owning integration's
|
|
metadata (the obj→device forward-sync skips linked objects too).
|
|
* ``parent_entry_id`` set → our own device, nested under the parent
|
|
object's device via ``via_device``.
|
|
* neither → our own stand-alone device (the historical shape).
|
|
"""
|
|
obj = self._object_data
|
|
hass = self.coordinator.hass
|
|
|
|
if device_id := obj.get("ha_device_id"):
|
|
device = dr.async_get(hass).async_get(device_id)
|
|
if device is not None and (device.identifiers or device.connections):
|
|
info = DeviceInfo()
|
|
if device.identifiers:
|
|
info["identifiers"] = device.identifiers
|
|
if device.connections:
|
|
info["connections"] = device.connections
|
|
return info
|
|
# Linked device vanished → fall through to an own device so the
|
|
# entities never end up device-less.
|
|
|
|
identifiers = {(DOMAIN, self.coordinator.entry.unique_id or "")}
|
|
|
|
device_info = DeviceInfo(
|
|
identifiers=identifiers,
|
|
name=obj.get("name", "Unknown"),
|
|
)
|
|
|
|
if obj.get("manufacturer"):
|
|
device_info["manufacturer"] = obj["manufacturer"]
|
|
if obj.get("model"):
|
|
device_info["model"] = obj["model"]
|
|
if obj.get("serial_number"):
|
|
device_info["serial_number"] = obj["serial_number"]
|
|
if obj.get("area_id"):
|
|
device_info["suggested_area"] = obj["area_id"]
|
|
|
|
if parent_entry_id := obj.get("parent_entry_id"):
|
|
parent = hass.config_entries.async_get_entry(parent_entry_id)
|
|
if parent is not None and parent.domain == DOMAIN and parent.unique_id and parent.unique_id != GLOBAL_UNIQUE_ID:
|
|
device_info["via_device"] = (DOMAIN, parent.unique_id)
|
|
|
|
return device_info
|
|
|
|
@property
|
|
def _task_data(self) -> dict[str, Any]:
|
|
"""Return the current task data from coordinator."""
|
|
if self.coordinator.data is None:
|
|
return {}
|
|
tasks: dict[str, Any] = self.coordinator.data.get("tasks", {})
|
|
result: dict[str, Any] = tasks.get(self._task_id, {})
|
|
return result
|