mirror of
https://github.com/home-assistant/core.git
synced 2025-07-22 20:57:21 +00:00
Add support for area field from pylutron_caseta (#80221)
This commit is contained in:
parent
4cf0f9b197
commit
01c66aa7c1
@ -177,7 +177,7 @@ async def async_setup_entry(
|
||||
)
|
||||
|
||||
buttons = bridge.buttons
|
||||
_async_register_bridge_device(hass, entry_id, bridge_device)
|
||||
_async_register_bridge_device(hass, entry_id, bridge_device, bridge)
|
||||
button_devices, device_info_by_device_id = _async_register_button_devices(
|
||||
hass, entry_id, bridge, bridge_device, buttons
|
||||
)
|
||||
@ -196,18 +196,25 @@ async def async_setup_entry(
|
||||
|
||||
@callback
|
||||
def _async_register_bridge_device(
|
||||
hass: HomeAssistant, config_entry_id: str, bridge_device: dict
|
||||
hass: HomeAssistant, config_entry_id: str, bridge_device: dict, bridge: Smartbridge
|
||||
) -> None:
|
||||
"""Register the bridge device in the device registry."""
|
||||
device_registry = dr.async_get(hass)
|
||||
device_registry.async_get_or_create(
|
||||
name=bridge_device["name"],
|
||||
manufacturer=MANUFACTURER,
|
||||
config_entry_id=config_entry_id,
|
||||
identifiers={(DOMAIN, bridge_device["serial"])},
|
||||
model=f"{bridge_device['model']} ({bridge_device['type']})",
|
||||
configuration_url="https://device-login.lutron.com",
|
||||
)
|
||||
|
||||
device_args: DeviceInfo = {
|
||||
"name": bridge_device["name"],
|
||||
"manufacturer": MANUFACTURER,
|
||||
"identifiers": {(DOMAIN, bridge_device["serial"])},
|
||||
"model": f"{bridge_device['model']} ({bridge_device['type']})",
|
||||
"via_device": (DOMAIN, bridge_device["serial"]),
|
||||
"configuration_url": "https://device-login.lutron.com",
|
||||
}
|
||||
|
||||
area = _area_name_from_id(bridge.areas, bridge_device["area"])
|
||||
if area != UNASSIGNED_AREA:
|
||||
device_args["suggested_area"] = area
|
||||
|
||||
device_registry.async_get_or_create(**device_args, config_entry_id=config_entry_id)
|
||||
|
||||
|
||||
@callback
|
||||
@ -241,7 +248,10 @@ def _async_register_button_devices(
|
||||
continue
|
||||
seen.add(ha_device_serial)
|
||||
|
||||
area, name = _area_and_name_from_name(ha_device["name"])
|
||||
area = _area_name_from_id(bridge.areas, ha_device["area"])
|
||||
# name field is still a combination of area and name from pylytron-caseta
|
||||
# extract the name portion only.
|
||||
name = ha_device["name"].split("_")[-1]
|
||||
device_args: DeviceInfo = {
|
||||
"name": f"{area} {name}",
|
||||
"manufacturer": MANUFACTURER,
|
||||
@ -265,12 +275,19 @@ def _handle_none_keypad_serial(keypad_device: dict, bridge_serial: int) -> str:
|
||||
return keypad_device["serial"] or f"{bridge_serial}_{keypad_device['device_id']}"
|
||||
|
||||
|
||||
def _area_and_name_from_name(device_name: str) -> tuple[str, str]:
|
||||
"""Return the area and name from the devices internal name."""
|
||||
if "_" in device_name:
|
||||
area_device_name = device_name.split("_", 1)
|
||||
return area_device_name[0], area_device_name[1]
|
||||
return UNASSIGNED_AREA, device_name
|
||||
def _area_name_from_id(areas: dict[str, dict], area_id: str) -> str:
|
||||
"""Return the full area name including parent(s)."""
|
||||
|
||||
if area_id is None:
|
||||
return UNASSIGNED_AREA
|
||||
|
||||
area = areas[area_id]
|
||||
if "parent_id" in area:
|
||||
parent_area = area["parent_id"]
|
||||
if parent_area is not None:
|
||||
return f"{_area_name_from_id(areas, parent_area)} {area['name']}"
|
||||
|
||||
return area["name"]
|
||||
|
||||
|
||||
@callback
|
||||
@ -316,7 +333,8 @@ def _async_subscribe_pico_remote_events(
|
||||
)
|
||||
|
||||
type_ = _lutron_model_to_device_type(ha_device["model"], ha_device["type"])
|
||||
area, name = _area_and_name_from_name(ha_device["name"])
|
||||
area = _area_name_from_id(bridge_device.areas, ha_device["area"])
|
||||
name = ha_device["name"].split("_")[-1]
|
||||
leap_button_number = device["button_number"]
|
||||
lip_button_number = async_get_lip_button(type_, leap_button_number)
|
||||
hass_device = dev_reg.async_get_device({(DOMAIN, ha_device_serial)})
|
||||
@ -377,8 +395,8 @@ class LutronCasetaDevice(Entity):
|
||||
if "parent_device" in device:
|
||||
# This is a child entity, handle the naming in button.py and switch.py
|
||||
return
|
||||
|
||||
area, name = _area_and_name_from_name(device["name"])
|
||||
area = _area_name_from_id(self._smartbridge.areas, device["area"])
|
||||
name = device["name"].split("_")[-1]
|
||||
self._attr_name = full_name = f"{area} {name}"
|
||||
info = DeviceInfo(
|
||||
# Historically we used the device serial number for the identifier
|
||||
|
@ -6,13 +6,14 @@ from homeassistant.components.binary_sensor import (
|
||||
BinarySensorEntity,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import ATTR_SUGGESTED_AREA
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.device_registry import DeviceEntryType
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import DOMAIN as CASETA_DOMAIN, LutronCasetaDevice, _area_and_name_from_name
|
||||
from .const import CONFIG_URL, MANUFACTURER
|
||||
from . import DOMAIN as CASETA_DOMAIN, LutronCasetaDevice, _area_name_from_id
|
||||
from .const import CONFIG_URL, MANUFACTURER, UNASSIGNED_AREA
|
||||
from .models import LutronCasetaData
|
||||
|
||||
|
||||
@ -43,7 +44,8 @@ class LutronOccupancySensor(LutronCasetaDevice, BinarySensorEntity):
|
||||
def __init__(self, device, data):
|
||||
"""Init an occupancy sensor."""
|
||||
super().__init__(device, data)
|
||||
_, name = _area_and_name_from_name(device["name"])
|
||||
area = _area_name_from_id(self._smartbridge.areas, device["area"])
|
||||
name = f"{area} {device['device_name']}"
|
||||
self._attr_name = name
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(CASETA_DOMAIN, self.unique_id)},
|
||||
@ -54,6 +56,8 @@ class LutronOccupancySensor(LutronCasetaDevice, BinarySensorEntity):
|
||||
configuration_url=CONFIG_URL,
|
||||
entry_type=DeviceEntryType.SERVICE,
|
||||
)
|
||||
if area != UNASSIGNED_AREA:
|
||||
self._attr_device_info[ATTR_SUGGESTED_AREA] = area
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
|
@ -9,7 +9,6 @@ from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import _area_and_name_from_name
|
||||
from .const import DOMAIN as CASETA_DOMAIN
|
||||
from .models import LutronCasetaData
|
||||
from .util import serial_to_unique_id
|
||||
@ -42,7 +41,7 @@ class LutronCasetaScene(Scene):
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(CASETA_DOMAIN, data.bridge_device["serial"])},
|
||||
)
|
||||
self._attr_name = _area_and_name_from_name(scene["name"])[1]
|
||||
self._attr_name = scene["name"]
|
||||
self._attr_unique_id = f"scene_{bridge_unique_id}_{self._scene_id}"
|
||||
|
||||
async def async_activate(self, **kwargs: Any) -> None:
|
||||
|
@ -105,7 +105,7 @@ class MockBridge:
|
||||
"""Initialize MockBridge instance with configured mock connectivity."""
|
||||
self.can_connect = can_connect
|
||||
self.is_currently_connected = False
|
||||
self.areas = {}
|
||||
self.areas = self.load_areas()
|
||||
self.occupancy_groups = {}
|
||||
self.scenes = self.get_scenes()
|
||||
self.devices = self.load_devices()
|
||||
@ -126,10 +126,28 @@ class MockBridge:
|
||||
"""Return whether the mock bridge is connected."""
|
||||
return self.is_currently_connected
|
||||
|
||||
def load_areas(self):
|
||||
"""Loak mock areas into self.areas."""
|
||||
return {
|
||||
"898": {"id": "898", "name": "Basement", "parent_id": None},
|
||||
"822": {"id": "822", "name": "Bedroom", "parent_id": "898"},
|
||||
"910": {"id": "910", "name": "Bathroom", "parent_id": "898"},
|
||||
"1024": {"id": "1024", "name": "Master Bedroom", "parent_id": None},
|
||||
"1025": {"id": "1025", "name": "Kitchen", "parent_id": None},
|
||||
"1026": {"id": "1026", "name": "Dining Room", "parent_id": None},
|
||||
"1205": {"id": "1205", "name": "Hallway", "parent_id": None},
|
||||
}
|
||||
|
||||
def load_devices(self):
|
||||
"""Load mock devices into self.devices."""
|
||||
return {
|
||||
"1": {"serial": 1234, "name": "bridge", "model": "model", "type": "type"},
|
||||
"1": {
|
||||
"serial": 1234,
|
||||
"name": "bridge",
|
||||
"model": "model",
|
||||
"type": "type",
|
||||
"area": "1205",
|
||||
},
|
||||
"801": {
|
||||
"device_id": "801",
|
||||
"current_state": 100,
|
||||
@ -141,6 +159,7 @@ class MockBridge:
|
||||
"model": None,
|
||||
"serial": None,
|
||||
"tilt": None,
|
||||
"area": "822",
|
||||
},
|
||||
"802": {
|
||||
"device_id": "802",
|
||||
@ -153,6 +172,7 @@ class MockBridge:
|
||||
"model": None,
|
||||
"serial": None,
|
||||
"tilt": None,
|
||||
"area": "822",
|
||||
},
|
||||
"803": {
|
||||
"device_id": "803",
|
||||
@ -165,6 +185,7 @@ class MockBridge:
|
||||
"model": None,
|
||||
"serial": None,
|
||||
"tilt": None,
|
||||
"area": "910",
|
||||
},
|
||||
"804": {
|
||||
"device_id": "804",
|
||||
@ -177,6 +198,7 @@ class MockBridge:
|
||||
"model": None,
|
||||
"serial": None,
|
||||
"tilt": None,
|
||||
"area": "1024",
|
||||
},
|
||||
"901": {
|
||||
"device_id": "901",
|
||||
@ -189,6 +211,7 @@ class MockBridge:
|
||||
"model": None,
|
||||
"serial": 5442321,
|
||||
"tilt": None,
|
||||
"area": "1025",
|
||||
},
|
||||
"9": {
|
||||
"device_id": "9",
|
||||
@ -203,7 +226,7 @@ class MockBridge:
|
||||
"model": "PJ2-3BRL-GXX-X01",
|
||||
"serial": 68551522,
|
||||
"device_name": "Pico",
|
||||
"area": "6",
|
||||
"area": "1026",
|
||||
},
|
||||
"1355": {
|
||||
"device_id": "1355",
|
||||
|
@ -40,7 +40,15 @@ async def test_diagnostics(hass, hass_client) -> None:
|
||||
diag = await get_diagnostics_for_config_entry(hass, hass_client, config_entry)
|
||||
assert diag == {
|
||||
"data": {
|
||||
"areas": {},
|
||||
"areas": {
|
||||
"898": {"id": "898", "name": "Basement", "parent_id": None},
|
||||
"822": {"id": "822", "name": "Bedroom", "parent_id": "898"},
|
||||
"910": {"id": "910", "name": "Bathroom", "parent_id": "898"},
|
||||
"1024": {"id": "1024", "name": "Master Bedroom", "parent_id": None},
|
||||
"1025": {"id": "1025", "name": "Kitchen", "parent_id": None},
|
||||
"1026": {"id": "1026", "name": "Dining Room", "parent_id": None},
|
||||
"1205": {"id": "1205", "name": "Hallway", "parent_id": None},
|
||||
},
|
||||
"buttons": {
|
||||
"111": {
|
||||
"device_id": "111",
|
||||
@ -73,6 +81,7 @@ async def test_diagnostics(hass, hass_client) -> None:
|
||||
"name": "bridge",
|
||||
"serial": 1234,
|
||||
"type": "type",
|
||||
"area": "1205",
|
||||
},
|
||||
"801": {
|
||||
"device_id": "801",
|
||||
@ -85,6 +94,7 @@ async def test_diagnostics(hass, hass_client) -> None:
|
||||
"model": None,
|
||||
"serial": None,
|
||||
"tilt": None,
|
||||
"area": "822",
|
||||
},
|
||||
"802": {
|
||||
"device_id": "802",
|
||||
@ -97,6 +107,7 @@ async def test_diagnostics(hass, hass_client) -> None:
|
||||
"model": None,
|
||||
"serial": None,
|
||||
"tilt": None,
|
||||
"area": "822",
|
||||
},
|
||||
"803": {
|
||||
"device_id": "803",
|
||||
@ -109,6 +120,7 @@ async def test_diagnostics(hass, hass_client) -> None:
|
||||
"model": None,
|
||||
"serial": None,
|
||||
"tilt": None,
|
||||
"area": "910",
|
||||
},
|
||||
"804": {
|
||||
"device_id": "804",
|
||||
@ -121,6 +133,7 @@ async def test_diagnostics(hass, hass_client) -> None:
|
||||
"model": None,
|
||||
"serial": None,
|
||||
"tilt": None,
|
||||
"area": "1024",
|
||||
},
|
||||
"901": {
|
||||
"device_id": "901",
|
||||
@ -133,6 +146,7 @@ async def test_diagnostics(hass, hass_client) -> None:
|
||||
"model": None,
|
||||
"serial": 5442321,
|
||||
"tilt": None,
|
||||
"area": "1025",
|
||||
},
|
||||
"9": {
|
||||
"device_id": "9",
|
||||
@ -147,7 +161,7 @@ async def test_diagnostics(hass, hass_client) -> None:
|
||||
"model": "PJ2-3BRL-GXX-X01",
|
||||
"serial": 68551522,
|
||||
"device_name": "Pico",
|
||||
"area": "6",
|
||||
"area": "1026",
|
||||
},
|
||||
"1355": {
|
||||
"device_id": "1355",
|
||||
|
Loading…
x
Reference in New Issue
Block a user