mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Add device to Lutron (#107467)
* Add typing to Lutron platforms * Add devices to Lutron * Add devices to Lutron * Fix typing * Fix * Add name * Fix lights * Comment out ESA * Fix domain * Fix domain * Fix * Make generic keypad base class
This commit is contained in:
parent
43daf20be3
commit
d0da457a04
@ -17,6 +17,7 @@ from homeassistant.const import (
|
||||
from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant
|
||||
from homeassistant.data_entry_flow import FlowResultType
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
import homeassistant.helpers.device_registry as dr
|
||||
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.util import slugify
|
||||
@ -167,7 +168,7 @@ class LutronData:
|
||||
buttons: list[LutronButton]
|
||||
covers: list[tuple[str, Output]]
|
||||
lights: list[tuple[str, Output]]
|
||||
scenes: list[tuple[str, str, Button, Led]]
|
||||
scenes: list[tuple[str, Keypad, Button, Led]]
|
||||
switches: list[tuple[str, Output]]
|
||||
|
||||
|
||||
@ -218,11 +219,20 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
||||
(led for led in keypad.leds if led.number == button.number),
|
||||
None,
|
||||
)
|
||||
entry_data.scenes.append((area.name, keypad.name, button, led))
|
||||
entry_data.scenes.append((area.name, keypad, button, led))
|
||||
|
||||
entry_data.buttons.append(LutronButton(hass, area.name, keypad, button))
|
||||
if area.occupancy_group is not None:
|
||||
entry_data.binary_sensors.append((area.name, area.occupancy_group))
|
||||
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry.async_get_or_create(
|
||||
config_entry_id=config_entry.entry_id,
|
||||
identifiers={(DOMAIN, lutron_client.guid)},
|
||||
manufacturer="Lutron",
|
||||
name="Main repeater",
|
||||
)
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})[config_entry.entry_id] = entry_data
|
||||
|
||||
await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
|
||||
|
@ -58,14 +58,6 @@ class LutronOccupancySensor(LutronDevice, BinarySensorEntity):
|
||||
# Error cases will end up treated as unoccupied.
|
||||
return self._lutron_device.state == OccupancyGroup.State.OCCUPIED
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Return the name of the device."""
|
||||
# The default LutronDevice naming would create 'Kitchen Occ Kitchen',
|
||||
# but since there can only be one OccupancyGroup per area we go
|
||||
# with something shorter.
|
||||
return f"{self._area_name} Occupancy"
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> Mapping[str, Any] | None:
|
||||
"""Return the state attributes."""
|
||||
|
@ -51,6 +51,7 @@ class LutronCover(LutronDevice, CoverEntity):
|
||||
| CoverEntityFeature.SET_POSITION
|
||||
)
|
||||
_lutron_device: Output
|
||||
_attr_name = None
|
||||
|
||||
@property
|
||||
def is_closed(self) -> bool:
|
||||
|
@ -1,14 +1,19 @@
|
||||
"""Base class for Lutron devices."""
|
||||
|
||||
from pylutron import Lutron, LutronEntity, LutronEvent
|
||||
from pylutron import Keypad, Lutron, LutronEntity, LutronEvent
|
||||
|
||||
from homeassistant.const import ATTR_IDENTIFIERS, ATTR_VIA_DEVICE
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
from .const import DOMAIN
|
||||
|
||||
class LutronDevice(Entity):
|
||||
"""Representation of a Lutron device entity."""
|
||||
|
||||
class LutronBaseEntity(Entity):
|
||||
"""Base class for Lutron entities."""
|
||||
|
||||
_attr_should_poll = False
|
||||
_attr_has_entity_name = True
|
||||
|
||||
def __init__(
|
||||
self, area_name: str, lutron_device: LutronEntity, controller: Lutron
|
||||
@ -28,11 +33,6 @@ class LutronDevice(Entity):
|
||||
"""Run when invoked by pylutron when the device state changes."""
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Return the name of the device."""
|
||||
return f"{self._area_name} {self._lutron_device.name}"
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str | None:
|
||||
"""Return a unique ID."""
|
||||
@ -40,3 +40,43 @@ class LutronDevice(Entity):
|
||||
if self._lutron_device.uuid is None:
|
||||
return None
|
||||
return f"{self._controller.guid}_{self._lutron_device.uuid}"
|
||||
|
||||
|
||||
class LutronDevice(LutronBaseEntity):
|
||||
"""Representation of a Lutron device entity."""
|
||||
|
||||
def __init__(
|
||||
self, area_name: str, lutron_device: LutronEntity, controller: Lutron
|
||||
) -> None:
|
||||
"""Initialize the device."""
|
||||
super().__init__(area_name, lutron_device, controller)
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, lutron_device.uuid)},
|
||||
manufacturer="Lutron",
|
||||
name=lutron_device.name,
|
||||
suggested_area=area_name,
|
||||
via_device=(DOMAIN, controller.guid),
|
||||
)
|
||||
|
||||
|
||||
class LutronKeypad(LutronBaseEntity):
|
||||
"""Representation of a Lutron Keypad."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
area_name: str,
|
||||
lutron_device: LutronEntity,
|
||||
controller: Lutron,
|
||||
keypad: Keypad,
|
||||
) -> None:
|
||||
"""Initialize the device."""
|
||||
super().__init__(area_name, lutron_device, controller)
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, keypad.id)},
|
||||
manufacturer="Lutron",
|
||||
name=keypad.name,
|
||||
)
|
||||
if keypad.type == "MAIN_REPEATER":
|
||||
self._attr_device_info[ATTR_IDENTIFIERS].add((DOMAIN, controller.guid))
|
||||
else:
|
||||
self._attr_device_info[ATTR_VIA_DEVICE] = (DOMAIN, controller.guid)
|
||||
|
@ -52,6 +52,7 @@ class LutronLight(LutronDevice, LightEntity):
|
||||
_attr_supported_color_modes = {ColorMode.BRIGHTNESS}
|
||||
_lutron_device: Output
|
||||
_prev_brightness: int | None = None
|
||||
_attr_name = None
|
||||
|
||||
@property
|
||||
def brightness(self) -> int:
|
||||
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from pylutron import Button, Led, Lutron
|
||||
from pylutron import Button, Keypad, Lutron
|
||||
|
||||
from homeassistant.components.scene import Scene
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
@ -11,7 +11,7 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import DOMAIN, LutronData
|
||||
from .entity import LutronDevice
|
||||
from .entity import LutronKeypad
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
@ -28,14 +28,14 @@ async def async_setup_entry(
|
||||
|
||||
async_add_entities(
|
||||
[
|
||||
LutronScene(area_name, keypad_name, device, led, entry_data.client)
|
||||
for area_name, keypad_name, device, led in entry_data.scenes
|
||||
LutronScene(area_name, keypad, device, entry_data.client)
|
||||
for area_name, keypad, device, led in entry_data.scenes
|
||||
],
|
||||
True,
|
||||
)
|
||||
|
||||
|
||||
class LutronScene(LutronDevice, Scene):
|
||||
class LutronScene(LutronKeypad, Scene):
|
||||
"""Representation of a Lutron Scene."""
|
||||
|
||||
_lutron_device: Button
|
||||
@ -43,21 +43,14 @@ class LutronScene(LutronDevice, Scene):
|
||||
def __init__(
|
||||
self,
|
||||
area_name: str,
|
||||
keypad_name: str,
|
||||
keypad: Keypad,
|
||||
lutron_device: Button,
|
||||
lutron_led: Led,
|
||||
controller: Lutron,
|
||||
) -> None:
|
||||
"""Initialize the scene/button."""
|
||||
super().__init__(area_name, lutron_device, controller)
|
||||
self._keypad_name = keypad_name
|
||||
self._led = lutron_led
|
||||
super().__init__(area_name, lutron_device, controller, keypad)
|
||||
self._attr_name = lutron_device.name
|
||||
|
||||
def activate(self, **kwargs: Any) -> None:
|
||||
"""Activate the scene."""
|
||||
self._lutron_device.press()
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Return the name of the device."""
|
||||
return f"{self._area_name} {self._keypad_name}: {self._lutron_device.name}"
|
||||
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
||||
from collections.abc import Mapping
|
||||
from typing import Any
|
||||
|
||||
from pylutron import Button, Led, Lutron, Output
|
||||
from pylutron import Button, Keypad, Led, Lutron, Output
|
||||
|
||||
from homeassistant.components.switch import SwitchEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
@ -12,7 +12,7 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import DOMAIN, LutronData
|
||||
from .entity import LutronDevice
|
||||
from .entity import LutronDevice, LutronKeypad
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
@ -33,11 +33,9 @@ async def async_setup_entry(
|
||||
entities.append(LutronSwitch(area_name, device, entry_data.client))
|
||||
|
||||
# Add the indicator LEDs for scenes (keypad buttons)
|
||||
for area_name, keypad_name, scene, led in entry_data.scenes:
|
||||
for area_name, keypad, scene, led in entry_data.scenes:
|
||||
if led is not None:
|
||||
entities.append(
|
||||
LutronLed(area_name, keypad_name, scene, led, entry_data.client)
|
||||
)
|
||||
entities.append(LutronLed(area_name, keypad, scene, led, entry_data.client))
|
||||
async_add_entities(entities, True)
|
||||
|
||||
|
||||
@ -77,7 +75,7 @@ class LutronSwitch(LutronDevice, SwitchEntity):
|
||||
self._prev_state = self._lutron_device.level > 0
|
||||
|
||||
|
||||
class LutronLed(LutronDevice, SwitchEntity):
|
||||
class LutronLed(LutronKeypad, SwitchEntity):
|
||||
"""Representation of a Lutron Keypad LED."""
|
||||
|
||||
_lutron_device: Led
|
||||
@ -85,15 +83,15 @@ class LutronLed(LutronDevice, SwitchEntity):
|
||||
def __init__(
|
||||
self,
|
||||
area_name: str,
|
||||
keypad_name: str,
|
||||
keypad: Keypad,
|
||||
scene_device: Button,
|
||||
led_device: Led,
|
||||
controller: Lutron,
|
||||
) -> None:
|
||||
"""Initialize the switch."""
|
||||
self._keypad_name = keypad_name
|
||||
self._scene_name = scene_device.name
|
||||
super().__init__(area_name, led_device, controller)
|
||||
super().__init__(area_name, led_device, controller, keypad)
|
||||
self._keypad_name = keypad.name
|
||||
self._attr_name = scene_device.name
|
||||
|
||||
def turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the LED on."""
|
||||
@ -108,7 +106,7 @@ class LutronLed(LutronDevice, SwitchEntity):
|
||||
"""Return the state attributes."""
|
||||
return {
|
||||
"keypad": self._keypad_name,
|
||||
"scene": self._scene_name,
|
||||
"scene": self._attr_name,
|
||||
"led": self._lutron_device.name,
|
||||
}
|
||||
|
||||
@ -117,11 +115,6 @@ class LutronLed(LutronDevice, SwitchEntity):
|
||||
"""Return true if device is on."""
|
||||
return self._lutron_device.last_state
|
||||
|
||||
@property
|
||||
def name(self) -> str:
|
||||
"""Return the name of the LED."""
|
||||
return f"{self._area_name} {self._keypad_name}: {self._scene_name} LED"
|
||||
|
||||
def update(self) -> None:
|
||||
"""Call when forcing a refresh of the device."""
|
||||
# The following property getter actually triggers an update in Lutron
|
||||
|
Loading…
x
Reference in New Issue
Block a user