Home Assistant Unofficial Reference 2024.12.1
hue_event.py
Go to the documentation of this file.
1 """Handle forward of events transmitted by Hue devices to HASS."""
2 
3 from __future__ import annotations
4 
5 import logging
6 from typing import TYPE_CHECKING
7 
8 from aiohue.v2 import HueBridgeV2
9 from aiohue.v2.controllers.events import EventType
10 from aiohue.v2.models.button import Button
11 from aiohue.v2.models.relative_rotary import RelativeRotary
12 
13 from homeassistant.const import CONF_DEVICE_ID, CONF_ID, CONF_TYPE, CONF_UNIQUE_ID
14 from homeassistant.core import callback
15 from homeassistant.helpers import device_registry as dr
16 from homeassistant.util import slugify
17 
18 from ..const import ATTR_HUE_EVENT, CONF_SUBTYPE, DOMAIN
19 
20 CONF_CONTROL_ID = "control_id"
21 CONF_DURATION = "duration"
22 CONF_STEPS = "steps"
23 
24 if TYPE_CHECKING:
25  from ..bridge import HueBridge
26 
27 LOGGER = logging.getLogger(__name__)
28 
29 
30 async def async_setup_hue_events(bridge: HueBridge):
31  """Manage listeners for stateless Hue sensors that emit events."""
32  hass = bridge.hass
33  api: HueBridgeV2 = bridge.api # to satisfy typing
34  conf_entry = bridge.config_entry
35  dev_reg = dr.async_get(hass)
36 
37  btn_controller = api.sensors.button
38  rotary_controller = api.sensors.relative_rotary
39 
40  @callback
41  def handle_button_event(evt_type: EventType, hue_resource: Button) -> None:
42  """Handle event from Hue button resource controller."""
43  LOGGER.debug("Received button event: %s", hue_resource)
44 
45  # guard for missing button object on the resource
46  if hue_resource.button is None:
47  return
48 
49  hue_device = btn_controller.get_device(hue_resource.id)
50  device = dev_reg.async_get_device(identifiers={(DOMAIN, hue_device.id)})
51 
52  # Fire event
53  data = {
54  # send slugified entity name as id = backwards compatibility with previous version
55  CONF_ID: slugify(f"{hue_device.metadata.name} Button"),
56  CONF_DEVICE_ID: device.id, # type: ignore[union-attr]
57  CONF_UNIQUE_ID: hue_resource.id,
58  CONF_TYPE: hue_resource.button.button_report.event.value,
59  CONF_SUBTYPE: hue_resource.metadata.control_id,
60  }
61  hass.bus.async_fire(ATTR_HUE_EVENT, data)
62 
63  # add listener for updates from `button` resource
64  conf_entry.async_on_unload(
65  btn_controller.subscribe(
66  handle_button_event, event_filter=EventType.RESOURCE_UPDATED
67  )
68  )
69 
70  @callback
71  def handle_rotary_event(evt_type: EventType, hue_resource: RelativeRotary) -> None:
72  """Handle event from Hue relative_rotary resource controller."""
73  LOGGER.debug("Received relative_rotary event: %s", hue_resource)
74 
75  hue_device = btn_controller.get_device(hue_resource.id)
76  device = dev_reg.async_get_device(identifiers={(DOMAIN, hue_device.id)})
77 
78  # Fire event
79  data = {
80  CONF_DEVICE_ID: device.id, # type: ignore[union-attr]
81  CONF_UNIQUE_ID: hue_resource.id,
82  CONF_TYPE: hue_resource.relative_rotary.rotary_report.action.value,
83  CONF_SUBTYPE: hue_resource.relative_rotary.rotary_report.rotation.direction.value,
84  CONF_DURATION: hue_resource.relative_rotary.rotary_report.rotation.duration,
85  CONF_STEPS: hue_resource.relative_rotary.rotary_report.rotation.steps,
86  }
87  hass.bus.async_fire(ATTR_HUE_EVENT, data)
88 
89  # add listener for updates from `relative_rotary` resource
90  conf_entry.async_on_unload(
91  rotary_controller.subscribe(
92  handle_rotary_event, event_filter=EventType.RESOURCE_UPDATED
93  )
94  )
def async_setup_hue_events(HueBridge bridge)
Definition: hue_event.py:30