mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Add zha device entity (#14579)
* Add endpoint entity * Fix lint error * Add nwk address as device state attribute * Change to ZhaDeviceEntity * Show last_seen only if offline * Remove obsolete _discover_endpoint_info()
This commit is contained in:
parent
201fd4afee
commit
1c251009fe
@ -7,6 +7,7 @@ https://home-assistant.io/components/zha/
|
|||||||
import collections
|
import collections
|
||||||
import enum
|
import enum
|
||||||
import logging
|
import logging
|
||||||
|
import time
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -14,6 +15,7 @@ import homeassistant.helpers.config_validation as cv
|
|||||||
from homeassistant import const as ha_const
|
from homeassistant import const as ha_const
|
||||||
from homeassistant.helpers import discovery, entity
|
from homeassistant.helpers import discovery, entity
|
||||||
from homeassistant.util import slugify
|
from homeassistant.util import slugify
|
||||||
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
|
|
||||||
REQUIREMENTS = [
|
REQUIREMENTS = [
|
||||||
'bellows==0.7.0',
|
'bellows==0.7.0',
|
||||||
@ -139,6 +141,7 @@ class ApplicationListener:
|
|||||||
"""Initialize the listener."""
|
"""Initialize the listener."""
|
||||||
self._hass = hass
|
self._hass = hass
|
||||||
self._config = config
|
self._config = config
|
||||||
|
self._component = EntityComponent(_LOGGER, DOMAIN, hass)
|
||||||
self._device_registry = collections.defaultdict(list)
|
self._device_registry = collections.defaultdict(list)
|
||||||
hass.data[DISCOVERY_KEY] = hass.data.get(DISCOVERY_KEY, {})
|
hass.data[DISCOVERY_KEY] = hass.data.get(DISCOVERY_KEY, {})
|
||||||
|
|
||||||
@ -175,10 +178,17 @@ class ApplicationListener:
|
|||||||
import homeassistant.components.zha.const as zha_const
|
import homeassistant.components.zha.const as zha_const
|
||||||
zha_const.populate_data()
|
zha_const.populate_data()
|
||||||
|
|
||||||
|
device_manufacturer = device_model = None
|
||||||
|
|
||||||
for endpoint_id, endpoint in device.endpoints.items():
|
for endpoint_id, endpoint in device.endpoints.items():
|
||||||
if endpoint_id == 0: # ZDO
|
if endpoint_id == 0: # ZDO
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if endpoint.manufacturer is not None:
|
||||||
|
device_manufacturer = endpoint.manufacturer
|
||||||
|
if endpoint.model is not None:
|
||||||
|
device_model = endpoint.model
|
||||||
|
|
||||||
component = None
|
component = None
|
||||||
profile_clusters = ([], [])
|
profile_clusters = ([], [])
|
||||||
device_key = "{}-{}".format(device.ieee, endpoint_id)
|
device_key = "{}-{}".format(device.ieee, endpoint_id)
|
||||||
@ -247,6 +257,14 @@ class ApplicationListener:
|
|||||||
join,
|
join,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
endpoint_entity = ZhaDeviceEntity(
|
||||||
|
device,
|
||||||
|
device_manufacturer,
|
||||||
|
device_model,
|
||||||
|
self,
|
||||||
|
)
|
||||||
|
await self._component.async_add_entities([endpoint_entity])
|
||||||
|
|
||||||
def register_entity(self, ieee, entity_obj):
|
def register_entity(self, ieee, entity_obj):
|
||||||
"""Record the creation of a hass entity associated with ieee."""
|
"""Record the creation of a hass entity associated with ieee."""
|
||||||
self._device_registry[ieee].append(entity_obj)
|
self._device_registry[ieee].append(entity_obj)
|
||||||
@ -370,6 +388,77 @@ class Entity(entity.Entity):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ZhaDeviceEntity(entity.Entity):
|
||||||
|
"""A base class for ZHA devices."""
|
||||||
|
|
||||||
|
def __init__(self, device, manufacturer, model, application_listener,
|
||||||
|
keepalive_interval=7200, **kwargs):
|
||||||
|
"""Init ZHA endpoint entity."""
|
||||||
|
self._device_state_attributes = {
|
||||||
|
'nwk': '0x{0:04x}'.format(device.nwk),
|
||||||
|
'ieee': str(device.ieee),
|
||||||
|
'lqi': device.lqi,
|
||||||
|
'rssi': device.rssi,
|
||||||
|
}
|
||||||
|
|
||||||
|
ieee = device.ieee
|
||||||
|
ieeetail = ''.join(['%02x' % (o, ) for o in ieee[-4:]])
|
||||||
|
if manufacturer is not None and model is not None:
|
||||||
|
self._unique_id = "{}_{}_{}".format(
|
||||||
|
slugify(manufacturer),
|
||||||
|
slugify(model),
|
||||||
|
ieeetail,
|
||||||
|
)
|
||||||
|
self._device_state_attributes['friendly_name'] = "{} {}".format(
|
||||||
|
manufacturer,
|
||||||
|
model,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self._unique_id = str(ieeetail)
|
||||||
|
|
||||||
|
self._device = device
|
||||||
|
self._state = 'offline'
|
||||||
|
self._keepalive_interval = keepalive_interval
|
||||||
|
|
||||||
|
application_listener.register_entity(ieee, self)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def unique_id(self) -> str:
|
||||||
|
"""Return a unique ID."""
|
||||||
|
return self._unique_id
|
||||||
|
|
||||||
|
@property
|
||||||
|
def state(self) -> str:
|
||||||
|
"""Return the state of the entity."""
|
||||||
|
return self._state
|
||||||
|
|
||||||
|
@property
|
||||||
|
def device_state_attributes(self):
|
||||||
|
"""Return device specific state attributes."""
|
||||||
|
update_time = None
|
||||||
|
if self._device.last_seen is not None and self._state == 'offline':
|
||||||
|
time_struct = time.localtime(self._device.last_seen)
|
||||||
|
update_time = time.strftime("%Y-%m-%dT%H:%M:%S", time_struct)
|
||||||
|
self._device_state_attributes['last_seen'] = update_time
|
||||||
|
if ('last_seen' in self._device_state_attributes and
|
||||||
|
self._state != 'offline'):
|
||||||
|
del self._device_state_attributes['last_seen']
|
||||||
|
self._device_state_attributes['lqi'] = self._device.lqi
|
||||||
|
self._device_state_attributes['rssi'] = self._device.rssi
|
||||||
|
return self._device_state_attributes
|
||||||
|
|
||||||
|
async def async_update(self):
|
||||||
|
"""Handle polling."""
|
||||||
|
if self._device.last_seen is None:
|
||||||
|
self._state = 'offline'
|
||||||
|
else:
|
||||||
|
difference = time.time() - self._device.last_seen
|
||||||
|
if difference > self._keepalive_interval:
|
||||||
|
self._state = 'offline'
|
||||||
|
else:
|
||||||
|
self._state = 'online'
|
||||||
|
|
||||||
|
|
||||||
def get_discovery_info(hass, discovery_info):
|
def get_discovery_info(hass, discovery_info):
|
||||||
"""Get the full discovery info for a device.
|
"""Get the full discovery info for a device.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user