mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 12:47:08 +00:00
Add event platform to Lutron (#109121)
* Add event platform to Lutron * Add event platform to Lutron * Fix * Fix * Fix * Add deprecation note * Fix * Fix * Update homeassistant/components/lutron/event.py * Update homeassistant/components/lutron/event.py * Fix
This commit is contained in:
parent
85203aeb28
commit
2977ec4872
@ -741,6 +741,7 @@ omit =
|
||||
homeassistant/components/lutron/binary_sensor.py
|
||||
homeassistant/components/lutron/cover.py
|
||||
homeassistant/components/lutron/entity.py
|
||||
homeassistant/components/lutron/event.py
|
||||
homeassistant/components/lutron/fan.py
|
||||
homeassistant/components/lutron/light.py
|
||||
homeassistant/components/lutron/switch.py
|
||||
|
@ -3,31 +3,25 @@
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
|
||||
from pylutron import Button, Keypad, Led, Lutron, LutronEvent, OccupancyGroup, Output
|
||||
from pylutron import Button, Keypad, Led, Lutron, OccupancyGroup, Output
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
ATTR_ID,
|
||||
CONF_HOST,
|
||||
CONF_PASSWORD,
|
||||
CONF_USERNAME,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME, Platform
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
from homeassistant.helpers import device_registry as dr, entity_registry as er
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.util import slugify
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
PLATFORMS = [
|
||||
Platform.BINARY_SENSOR,
|
||||
Platform.COVER,
|
||||
Platform.EVENT,
|
||||
Platform.FAN,
|
||||
Platform.LIGHT,
|
||||
Platform.SCENE,
|
||||
@ -105,69 +99,13 @@ async def async_setup(hass: HomeAssistant, base_config: ConfigType) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
class LutronButton:
|
||||
"""Representation of a button on a Lutron keypad.
|
||||
|
||||
This is responsible for firing events as keypad buttons are pressed
|
||||
(and possibly released, depending on the button type). It is not
|
||||
represented as an entity; it simply fires events.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, hass: HomeAssistant, area_name: str, keypad: Keypad, button: Button
|
||||
) -> None:
|
||||
"""Register callback for activity on the button."""
|
||||
name = f"{keypad.name}: {button.name}"
|
||||
if button.name == "Unknown Button":
|
||||
name += f" {button.number}"
|
||||
self._hass = hass
|
||||
self._has_release_event = (
|
||||
button.button_type is not None and "RaiseLower" in button.button_type
|
||||
)
|
||||
self._id = slugify(name)
|
||||
self._keypad = keypad
|
||||
self._area_name = area_name
|
||||
self._button_name = button.name
|
||||
self._button = button
|
||||
self._event = "lutron_event"
|
||||
self._full_id = slugify(f"{area_name} {name}")
|
||||
self._uuid = button.uuid
|
||||
|
||||
button.subscribe(self.button_callback, None)
|
||||
|
||||
def button_callback(
|
||||
self, _button: Button, _context: None, event: LutronEvent, _params: dict
|
||||
) -> None:
|
||||
"""Fire an event about a button being pressed or released."""
|
||||
# Events per button type:
|
||||
# RaiseLower -> pressed/released
|
||||
# SingleAction -> single
|
||||
action = None
|
||||
if self._has_release_event:
|
||||
if event == Button.Event.PRESSED:
|
||||
action = "pressed"
|
||||
else:
|
||||
action = "released"
|
||||
elif event == Button.Event.PRESSED:
|
||||
action = "single"
|
||||
|
||||
if action:
|
||||
data = {
|
||||
ATTR_ID: self._id,
|
||||
ATTR_ACTION: action,
|
||||
ATTR_FULL_ID: self._full_id,
|
||||
ATTR_UUID: self._uuid,
|
||||
}
|
||||
self._hass.bus.fire(self._event, data)
|
||||
|
||||
|
||||
@dataclass(slots=True, kw_only=True)
|
||||
class LutronData:
|
||||
"""Storage class for platform global data."""
|
||||
|
||||
client: Lutron
|
||||
binary_sensors: list[tuple[str, OccupancyGroup]]
|
||||
buttons: list[LutronButton]
|
||||
buttons: list[tuple[str, Keypad, Button]]
|
||||
covers: list[tuple[str, Output]]
|
||||
fans: list[tuple[str, Output]]
|
||||
lights: list[tuple[str, Output]]
|
||||
@ -273,8 +211,8 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
||||
led.legacy_uuid,
|
||||
entry_data.client.guid,
|
||||
)
|
||||
|
||||
entry_data.buttons.append(LutronButton(hass, area.name, keypad, button))
|
||||
if button.button_type:
|
||||
entry_data.buttons.append((area.name, keypad, button))
|
||||
if area.occupancy_group is not None:
|
||||
entry_data.binary_sensors.append((area.name, area.occupancy_group))
|
||||
platform = Platform.BINARY_SENSOR
|
||||
|
109
homeassistant/components/lutron/event.py
Normal file
109
homeassistant/components/lutron/event.py
Normal file
@ -0,0 +1,109 @@
|
||||
"""Support for Lutron events."""
|
||||
|
||||
from enum import StrEnum
|
||||
|
||||
from pylutron import Button, Keypad, Lutron, LutronEvent
|
||||
|
||||
from homeassistant.components.event import EventEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ATTR_ID
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.util import slugify
|
||||
|
||||
from . import ATTR_ACTION, ATTR_FULL_ID, ATTR_UUID, DOMAIN, LutronData
|
||||
from .entity import LutronKeypad
|
||||
|
||||
|
||||
class LutronEventType(StrEnum):
|
||||
"""Lutron event types."""
|
||||
|
||||
SINGLE_PRESS = "single_press"
|
||||
PRESS = "press"
|
||||
RELEASE = "release"
|
||||
|
||||
|
||||
LEGACY_EVENT_TYPES: dict[LutronEventType, str] = {
|
||||
LutronEventType.SINGLE_PRESS: "single",
|
||||
LutronEventType.PRESS: "pressed",
|
||||
LutronEventType.RELEASE: "released",
|
||||
}
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the Lutron event platform."""
|
||||
entry_data: LutronData = hass.data[DOMAIN][config_entry.entry_id]
|
||||
|
||||
async_add_entities(
|
||||
LutronEventEntity(area_name, keypad, button, entry_data.client)
|
||||
for area_name, keypad, button in entry_data.buttons
|
||||
)
|
||||
|
||||
|
||||
class LutronEventEntity(LutronKeypad, EventEntity):
|
||||
"""Representation of a Lutron keypad button."""
|
||||
|
||||
_attr_translation_key = "button"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
area_name: str,
|
||||
keypad: Keypad,
|
||||
button: Button,
|
||||
controller: Lutron,
|
||||
) -> None:
|
||||
"""Initialize the button."""
|
||||
super().__init__(area_name, button, controller, keypad)
|
||||
if (name := button.name) == "Unknown Button":
|
||||
name += f" {button.number}"
|
||||
self._attr_name = name
|
||||
self._has_release_event = (
|
||||
button.button_type is not None and "RaiseLower" in button.button_type
|
||||
)
|
||||
if self._has_release_event:
|
||||
self._attr_event_types = [LutronEventType.PRESS, LutronEventType.RELEASE]
|
||||
else:
|
||||
self._attr_event_types = [LutronEventType.SINGLE_PRESS]
|
||||
|
||||
self._full_id = slugify(f"{area_name} {name}")
|
||||
self._id = slugify(name)
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register callbacks."""
|
||||
await super().async_added_to_hass()
|
||||
self._lutron_device.subscribe(self.handle_event, None)
|
||||
|
||||
async def async_will_remove_from_hass(self) -> None:
|
||||
"""Unregister callbacks."""
|
||||
await super().async_will_remove_from_hass()
|
||||
# Temporary solution until https://github.com/thecynic/pylutron/pull/93 gets merged
|
||||
self._lutron_device._subscribers.remove((self.handle_event, None)) # pylint: disable=protected-access
|
||||
|
||||
@callback
|
||||
def handle_event(
|
||||
self, button: Button, _context: None, event: LutronEvent, _params: dict
|
||||
) -> None:
|
||||
"""Handle received event."""
|
||||
action: LutronEventType | None = None
|
||||
if self._has_release_event:
|
||||
if event == Button.Event.PRESSED:
|
||||
action = LutronEventType.PRESS
|
||||
else:
|
||||
action = LutronEventType.RELEASE
|
||||
elif event == Button.Event.PRESSED:
|
||||
action = LutronEventType.SINGLE_PRESS
|
||||
|
||||
if action:
|
||||
data = {
|
||||
ATTR_ID: self._id,
|
||||
ATTR_ACTION: LEGACY_EVENT_TYPES[action],
|
||||
ATTR_FULL_ID: self._full_id,
|
||||
ATTR_UUID: button.uuid,
|
||||
}
|
||||
self.hass.bus.fire("lutron_event", data)
|
||||
self._trigger_event(action)
|
||||
self.async_write_ha_state()
|
@ -22,6 +22,21 @@
|
||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]"
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"event": {
|
||||
"button": {
|
||||
"state_attributes": {
|
||||
"event_type": {
|
||||
"state": {
|
||||
"single_press": "Single press",
|
||||
"press": "Press",
|
||||
"release": "Release"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"deprecated_yaml_import_issue_cannot_connect": {
|
||||
"title": "The Lutron YAML configuration import cannot connect to server",
|
||||
|
Loading…
x
Reference in New Issue
Block a user