"""Base class for deCONZ devices.""" from __future__ import annotations from homeassistant.core import callback from homeassistant.helpers.device_registry import CONNECTION_ZIGBEE from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity import DeviceInfo, Entity from .const import DOMAIN as DECONZ_DOMAIN class DeconzBase: """Common base for deconz entities and events.""" def __init__(self, device, gateway): """Set up device and add update callback to get data from websocket.""" self._device = device self.gateway = gateway @property def unique_id(self): """Return a unique identifier for this device.""" return self._device.unique_id @property def serial(self): """Return a serial number for this device.""" if self._device.unique_id is None or self._device.unique_id.count(":") != 7: return None return self._device.unique_id.split("-", 1)[0] @property def device_info(self) -> DeviceInfo | None: """Return a device description for device registry.""" if self.serial is None: return None return DeviceInfo( connections={(CONNECTION_ZIGBEE, self.serial)}, identifiers={(DECONZ_DOMAIN, self.serial)}, manufacturer=self._device.manufacturer, model=self._device.model_id, name=self._device.name, sw_version=self._device.software_version, via_device=(DECONZ_DOMAIN, self.gateway.api.config.bridge_id), ) class DeconzDevice(DeconzBase, Entity): """Representation of a deCONZ device.""" _attr_should_poll = False TYPE = "" def __init__(self, device, gateway): """Set up device and add update callback to get data from websocket.""" super().__init__(device, gateway) self.gateway.entities[self.TYPE].add(self.unique_id) self._attr_name = self._device.name async def async_added_to_hass(self): """Subscribe to device events.""" self._device.register_callback(self.async_update_callback) self.gateway.deconz_ids[self.entity_id] = self._device.deconz_id self.async_on_remove( async_dispatcher_connect( self.hass, self.gateway.signal_reachable, self.async_update_connection_state, ) ) async def async_will_remove_from_hass(self) -> None: """Disconnect device object when removed.""" self._device.remove_callback(self.async_update_callback) del self.gateway.deconz_ids[self.entity_id] self.gateway.entities[self.TYPE].remove(self.unique_id) @callback def async_update_connection_state(self): """Update the device's available state.""" self.async_write_ha_state() @callback def async_update_callback(self): """Update the device's state.""" if self.gateway.ignore_state_updates: return self.async_write_ha_state() @property def available(self): """Return True if device is available.""" return self.gateway.available and self._device.reachable