Home Assistant Unofficial Reference 2024.12.1
device.py
Go to the documentation of this file.
1 """Handles Hue resource of type `device` mapping to Home Assistant device."""
2 
3 from __future__ import annotations
4 
5 from typing import TYPE_CHECKING
6 
7 from aiohue.v2 import HueBridgeV2
8 from aiohue.v2.controllers.events import EventType
9 from aiohue.v2.controllers.groups import Room, Zone
10 from aiohue.v2.models.device import Device, DeviceArchetypes
11 from aiohue.v2.models.resource import ResourceTypes
12 
13 from homeassistant.const import (
14  ATTR_CONNECTIONS,
15  ATTR_IDENTIFIERS,
16  ATTR_MANUFACTURER,
17  ATTR_MODEL,
18  ATTR_NAME,
19  ATTR_SUGGESTED_AREA,
20  ATTR_SW_VERSION,
21  ATTR_VIA_DEVICE,
22 )
23 from homeassistant.core import callback
24 from homeassistant.helpers import device_registry as dr
25 
26 from ..const import DOMAIN
27 
28 if TYPE_CHECKING:
29  from ..bridge import HueBridge
30 
31 
32 async def async_setup_devices(bridge: HueBridge):
33  """Manage setup of devices from Hue devices."""
34  entry = bridge.config_entry
35  hass = bridge.hass
36  api: HueBridgeV2 = bridge.api # to satisfy typing
37  dev_reg = dr.async_get(hass)
38  dev_controller = api.devices
39 
40  @callback
41  def add_device(hue_resource: Device | Room | Zone) -> dr.DeviceEntry:
42  """Register a Hue device in device registry."""
43  if isinstance(hue_resource, (Room, Zone)):
44  # Register a Hue Room/Zone as service in HA device registry.
45  return dev_reg.async_get_or_create(
46  config_entry_id=entry.entry_id,
47  entry_type=dr.DeviceEntryType.SERVICE,
48  identifiers={(DOMAIN, hue_resource.id)},
49  name=hue_resource.metadata.name,
50  model=hue_resource.type.value.title(),
51  manufacturer=api.config.bridge_device.product_data.manufacturer_name,
52  via_device=(DOMAIN, api.config.bridge_device.id),
53  suggested_area=hue_resource.metadata.name
54  if hue_resource.type == ResourceTypes.ROOM
55  else None,
56  )
57  # Register a Hue device resource as device in HA device registry.
58  model = f"{hue_resource.product_data.product_name} ({hue_resource.product_data.model_id})"
59  params = {
60  ATTR_IDENTIFIERS: {(DOMAIN, hue_resource.id)},
61  ATTR_SW_VERSION: hue_resource.product_data.software_version,
62  ATTR_NAME: hue_resource.metadata.name,
63  ATTR_MODEL: model,
64  ATTR_MANUFACTURER: hue_resource.product_data.manufacturer_name,
65  }
66  if room := dev_controller.get_room(hue_resource.id):
67  params[ATTR_SUGGESTED_AREA] = room.metadata.name
68  if hue_resource.metadata.archetype == DeviceArchetypes.BRIDGE_V2:
69  params[ATTR_IDENTIFIERS].add((DOMAIN, api.config.bridge_id))
70  else:
71  params[ATTR_VIA_DEVICE] = (DOMAIN, api.config.bridge_device.id)
72  zigbee = dev_controller.get_zigbee_connectivity(hue_resource.id)
73  if zigbee and zigbee.mac_address:
74  params[ATTR_CONNECTIONS] = {(dr.CONNECTION_NETWORK_MAC, zigbee.mac_address)}
75 
76  return dev_reg.async_get_or_create(config_entry_id=entry.entry_id, **params)
77 
78  @callback
79  def remove_device(hue_device_id: str) -> None:
80  """Remove device from registry."""
81  if device := dev_reg.async_get_device(identifiers={(DOMAIN, hue_device_id)}):
82  # note: removal of any underlying entities is handled by core
83  dev_reg.async_remove_device(device.id)
84 
85  @callback
86  def handle_device_event(
87  evt_type: EventType, hue_resource: Device | Room | Zone
88  ) -> None:
89  """Handle event from Hue controller."""
90  if evt_type == EventType.RESOURCE_DELETED:
91  remove_device(hue_resource.id)
92  else:
93  # updates to existing device will also be handled by this call
94  add_device(hue_resource)
95 
96  # create/update all current devices found in controllers
97  known_devices = [add_device(hue_device) for hue_device in dev_controller]
98  known_devices += [add_device(hue_room) for hue_room in api.groups.room]
99  known_devices += [add_device(hue_zone) for hue_zone in api.groups.zone]
100 
101  # Check for nodes that no longer exist and remove them
102  for device in dr.async_entries_for_config_entry(dev_reg, entry.entry_id):
103  if device not in known_devices:
104  dev_reg.async_remove_device(device.id)
105 
106  # add listener for updates on Hue controllers
107  entry.async_on_unload(dev_controller.subscribe(handle_device_event))
108  entry.async_on_unload(api.groups.room.subscribe(handle_device_event))
109  entry.async_on_unload(api.groups.zone.subscribe(handle_device_event))
bool add(self, _T matcher)
Definition: match.py:185
def async_setup_devices(HueBridge bridge)
Definition: device.py:32