mirror of https://github.com/home-assistant/core
110 lines
4.5 KiB
Python
110 lines
4.5 KiB
Python
"""Handles Hue resource of type `device` mapping to Home Assistant device."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING
|
|
|
|
from aiohue.v2 import HueBridgeV2
|
|
from aiohue.v2.controllers.events import EventType
|
|
from aiohue.v2.controllers.groups import Room, Zone
|
|
from aiohue.v2.models.device import Device, DeviceArchetypes
|
|
from aiohue.v2.models.resource import ResourceTypes
|
|
|
|
from homeassistant.const import (
|
|
ATTR_CONNECTIONS,
|
|
ATTR_IDENTIFIERS,
|
|
ATTR_MANUFACTURER,
|
|
ATTR_MODEL,
|
|
ATTR_NAME,
|
|
ATTR_SUGGESTED_AREA,
|
|
ATTR_SW_VERSION,
|
|
ATTR_VIA_DEVICE,
|
|
)
|
|
from homeassistant.core import callback
|
|
from homeassistant.helpers import device_registry as dr
|
|
|
|
from ..const import DOMAIN
|
|
|
|
if TYPE_CHECKING:
|
|
from ..bridge import HueBridge
|
|
|
|
|
|
async def async_setup_devices(bridge: HueBridge):
|
|
"""Manage setup of devices from Hue devices."""
|
|
entry = bridge.config_entry
|
|
hass = bridge.hass
|
|
api: HueBridgeV2 = bridge.api # to satisfy typing
|
|
dev_reg = dr.async_get(hass)
|
|
dev_controller = api.devices
|
|
|
|
@callback
|
|
def add_device(hue_resource: Device | Room | Zone) -> dr.DeviceEntry:
|
|
"""Register a Hue device in device registry."""
|
|
if isinstance(hue_resource, (Room, Zone)):
|
|
# Register a Hue Room/Zone as service in HA device registry.
|
|
return dev_reg.async_get_or_create(
|
|
config_entry_id=entry.entry_id,
|
|
entry_type=dr.DeviceEntryType.SERVICE,
|
|
identifiers={(DOMAIN, hue_resource.id)},
|
|
name=hue_resource.metadata.name,
|
|
model=hue_resource.type.value.title(),
|
|
manufacturer=api.config.bridge_device.product_data.manufacturer_name,
|
|
via_device=(DOMAIN, api.config.bridge_device.id),
|
|
suggested_area=hue_resource.metadata.name
|
|
if hue_resource.type == ResourceTypes.ROOM
|
|
else None,
|
|
)
|
|
# Register a Hue device resource as device in HA device registry.
|
|
model = f"{hue_resource.product_data.product_name} ({hue_resource.product_data.model_id})"
|
|
params = {
|
|
ATTR_IDENTIFIERS: {(DOMAIN, hue_resource.id)},
|
|
ATTR_SW_VERSION: hue_resource.product_data.software_version,
|
|
ATTR_NAME: hue_resource.metadata.name,
|
|
ATTR_MODEL: model,
|
|
ATTR_MANUFACTURER: hue_resource.product_data.manufacturer_name,
|
|
}
|
|
if room := dev_controller.get_room(hue_resource.id):
|
|
params[ATTR_SUGGESTED_AREA] = room.metadata.name
|
|
if hue_resource.metadata.archetype == DeviceArchetypes.BRIDGE_V2:
|
|
params[ATTR_IDENTIFIERS].add((DOMAIN, api.config.bridge_id))
|
|
else:
|
|
params[ATTR_VIA_DEVICE] = (DOMAIN, api.config.bridge_device.id)
|
|
zigbee = dev_controller.get_zigbee_connectivity(hue_resource.id)
|
|
if zigbee and zigbee.mac_address:
|
|
params[ATTR_CONNECTIONS] = {(dr.CONNECTION_NETWORK_MAC, zigbee.mac_address)}
|
|
|
|
return dev_reg.async_get_or_create(config_entry_id=entry.entry_id, **params)
|
|
|
|
@callback
|
|
def remove_device(hue_device_id: str) -> None:
|
|
"""Remove device from registry."""
|
|
if device := dev_reg.async_get_device(identifiers={(DOMAIN, hue_device_id)}):
|
|
# note: removal of any underlying entities is handled by core
|
|
dev_reg.async_remove_device(device.id)
|
|
|
|
@callback
|
|
def handle_device_event(
|
|
evt_type: EventType, hue_resource: Device | Room | Zone
|
|
) -> None:
|
|
"""Handle event from Hue controller."""
|
|
if evt_type == EventType.RESOURCE_DELETED:
|
|
remove_device(hue_resource.id)
|
|
else:
|
|
# updates to existing device will also be handled by this call
|
|
add_device(hue_resource)
|
|
|
|
# create/update all current devices found in controllers
|
|
known_devices = [add_device(hue_device) for hue_device in dev_controller]
|
|
known_devices += [add_device(hue_room) for hue_room in api.groups.room]
|
|
known_devices += [add_device(hue_zone) for hue_zone in api.groups.zone]
|
|
|
|
# Check for nodes that no longer exist and remove them
|
|
for device in dr.async_entries_for_config_entry(dev_reg, entry.entry_id):
|
|
if device not in known_devices:
|
|
dev_reg.async_remove_device(device.id)
|
|
|
|
# add listener for updates on Hue controllers
|
|
entry.async_on_unload(dev_controller.subscribe(handle_device_event))
|
|
entry.async_on_unload(api.groups.room.subscribe(handle_device_event))
|
|
entry.async_on_unload(api.groups.zone.subscribe(handle_device_event))
|