Fix switch_as_x name (#91232)
This commit is contained in:
parent
aa68d1d617
commit
eb63bc7967
7 changed files with 176 additions and 8 deletions
|
@ -3,7 +3,11 @@ from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant.components.cover import CoverEntity, CoverEntityFeature
|
from homeassistant.components.cover import (
|
||||||
|
DOMAIN as COVER_DOMAIN,
|
||||||
|
CoverEntity,
|
||||||
|
CoverEntityFeature,
|
||||||
|
)
|
||||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
|
@ -36,6 +40,7 @@ async def async_setup_entry(
|
||||||
CoverSwitch(
|
CoverSwitch(
|
||||||
hass,
|
hass,
|
||||||
config_entry.title,
|
config_entry.title,
|
||||||
|
COVER_DOMAIN,
|
||||||
entity_id,
|
entity_id,
|
||||||
config_entry.entry_id,
|
config_entry.entry_id,
|
||||||
)
|
)
|
||||||
|
|
|
@ -23,13 +23,15 @@ class BaseEntity(Entity):
|
||||||
"""Represents a Switch as an X."""
|
"""Represents a Switch as an X."""
|
||||||
|
|
||||||
_attr_should_poll = False
|
_attr_should_poll = False
|
||||||
|
_is_new_entity: bool
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config_entry_title: str,
|
config_entry_title: str,
|
||||||
|
domain: str,
|
||||||
switch_entity_id: str,
|
switch_entity_id: str,
|
||||||
unique_id: str | None,
|
unique_id: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize Switch as an X."""
|
"""Initialize Switch as an X."""
|
||||||
registry = er.async_get(hass)
|
registry = er.async_get(hass)
|
||||||
|
@ -41,7 +43,7 @@ class BaseEntity(Entity):
|
||||||
|
|
||||||
name: str | None = config_entry_title
|
name: str | None = config_entry_title
|
||||||
if wrapped_switch:
|
if wrapped_switch:
|
||||||
name = wrapped_switch.name or wrapped_switch.original_name
|
name = wrapped_switch.original_name
|
||||||
|
|
||||||
self._device_id = device_id
|
self._device_id = device_id
|
||||||
if device_id and (device := device_registry.async_get(device_id)):
|
if device_id and (device := device_registry.async_get(device_id)):
|
||||||
|
@ -55,6 +57,10 @@ class BaseEntity(Entity):
|
||||||
self._attr_unique_id = unique_id
|
self._attr_unique_id = unique_id
|
||||||
self._switch_entity_id = switch_entity_id
|
self._switch_entity_id = switch_entity_id
|
||||||
|
|
||||||
|
self._is_new_entity = (
|
||||||
|
registry.async_get_entity_id(domain, SWITCH_AS_X_DOMAIN, unique_id) is None
|
||||||
|
)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_state_changed_listener(self, event: Event | None = None) -> None:
|
def async_state_changed_listener(self, event: Event | None = None) -> None:
|
||||||
"""Handle child updates."""
|
"""Handle child updates."""
|
||||||
|
@ -67,7 +73,7 @@ class BaseEntity(Entity):
|
||||||
self._attr_available = True
|
self._attr_available = True
|
||||||
|
|
||||||
async def async_added_to_hass(self) -> None:
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Register callbacks."""
|
"""Register callbacks and copy the wrapped entity's custom name if set."""
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _async_state_changed_listener(event: Event | None = None) -> None:
|
def _async_state_changed_listener(event: Event | None = None) -> None:
|
||||||
|
@ -93,6 +99,15 @@ class BaseEntity(Entity):
|
||||||
{"entity_id": self._switch_entity_id},
|
{"entity_id": self._switch_entity_id},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not self._is_new_entity:
|
||||||
|
return
|
||||||
|
|
||||||
|
wrapped_switch = registry.async_get(self._switch_entity_id)
|
||||||
|
if not wrapped_switch or wrapped_switch.name is None:
|
||||||
|
return
|
||||||
|
|
||||||
|
registry.async_update_entity(self.entity_id, name=wrapped_switch.name)
|
||||||
|
|
||||||
|
|
||||||
class BaseToggleEntity(BaseEntity, ToggleEntity):
|
class BaseToggleEntity(BaseEntity, ToggleEntity):
|
||||||
"""Represents a Switch as a ToggleEntity."""
|
"""Represents a Switch as a ToggleEntity."""
|
||||||
|
|
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant.components.fan import FanEntity
|
from homeassistant.components.fan import DOMAIN as FAN_DOMAIN, FanEntity
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_ENTITY_ID
|
from homeassistant.const import CONF_ENTITY_ID
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
@ -29,6 +29,7 @@ async def async_setup_entry(
|
||||||
FanSwitch(
|
FanSwitch(
|
||||||
hass,
|
hass,
|
||||||
config_entry.title,
|
config_entry.title,
|
||||||
|
FAN_DOMAIN,
|
||||||
entity_id,
|
entity_id,
|
||||||
config_entry.entry_id,
|
config_entry.entry_id,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
"""Light support for switch entities."""
|
"""Light support for switch entities."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from homeassistant.components.light import ColorMode, LightEntity
|
from homeassistant.components.light import (
|
||||||
|
DOMAIN as LIGHT_DOMAIN,
|
||||||
|
ColorMode,
|
||||||
|
LightEntity,
|
||||||
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_ENTITY_ID
|
from homeassistant.const import CONF_ENTITY_ID
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
@ -27,6 +31,7 @@ async def async_setup_entry(
|
||||||
LightSwitch(
|
LightSwitch(
|
||||||
hass,
|
hass,
|
||||||
config_entry.title,
|
config_entry.title,
|
||||||
|
LIGHT_DOMAIN,
|
||||||
entity_id,
|
entity_id,
|
||||||
config_entry.entry_id,
|
config_entry.entry_id,
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
||||||
|
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant.components.lock import LockEntity
|
from homeassistant.components.lock import DOMAIN as LOCK_DOMAIN, LockEntity
|
||||||
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
|
@ -36,6 +36,7 @@ async def async_setup_entry(
|
||||||
LockSwitch(
|
LockSwitch(
|
||||||
hass,
|
hass,
|
||||||
config_entry.title,
|
config_entry.title,
|
||||||
|
LOCK_DOMAIN,
|
||||||
entity_id,
|
entity_id,
|
||||||
config_entry.entry_id,
|
config_entry.entry_id,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
"""Siren support for switch entities."""
|
"""Siren support for switch entities."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from homeassistant.components.siren import SirenEntity, SirenEntityFeature
|
from homeassistant.components.siren import (
|
||||||
|
DOMAIN as SIREN_DOMAIN,
|
||||||
|
SirenEntity,
|
||||||
|
SirenEntityFeature,
|
||||||
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_ENTITY_ID
|
from homeassistant.const import CONF_ENTITY_ID
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
@ -27,6 +31,7 @@ async def async_setup_entry(
|
||||||
SirenSwitch(
|
SirenSwitch(
|
||||||
hass,
|
hass,
|
||||||
config_entry.title,
|
config_entry.title,
|
||||||
|
SIREN_DOMAIN,
|
||||||
entity_id,
|
entity_id,
|
||||||
config_entry.entry_id,
|
config_entry.entry_id,
|
||||||
)
|
)
|
||||||
|
|
|
@ -534,7 +534,143 @@ async def test_entity_name(
|
||||||
assert entity_entry
|
assert entity_entry
|
||||||
assert entity_entry.device_id == switch_entity_entry.device_id
|
assert entity_entry.device_id == switch_entity_entry.device_id
|
||||||
assert entity_entry.has_entity_name is True
|
assert entity_entry.has_entity_name is True
|
||||||
|
assert entity_entry.name is None
|
||||||
assert entity_entry.original_name is None
|
assert entity_entry.original_name is None
|
||||||
assert entity_entry.options == {
|
assert entity_entry.options == {
|
||||||
DOMAIN: {"entity_id": switch_entity_entry.entity_id}
|
DOMAIN: {"entity_id": switch_entity_entry.entity_id}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("target_domain", PLATFORMS_TO_TEST)
|
||||||
|
async def test_custom_name_1(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
target_domain: Platform,
|
||||||
|
) -> None:
|
||||||
|
"""Test the source entity has a custom name."""
|
||||||
|
registry = er.async_get(hass)
|
||||||
|
device_registry = dr.async_get(hass)
|
||||||
|
|
||||||
|
switch_config_entry = MockConfigEntry()
|
||||||
|
|
||||||
|
device_entry = device_registry.async_get_or_create(
|
||||||
|
config_entry_id=switch_config_entry.entry_id,
|
||||||
|
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
|
||||||
|
name="Device name",
|
||||||
|
)
|
||||||
|
|
||||||
|
switch_entity_entry = registry.async_get_or_create(
|
||||||
|
"switch",
|
||||||
|
"test",
|
||||||
|
"unique",
|
||||||
|
device_id=device_entry.id,
|
||||||
|
has_entity_name=True,
|
||||||
|
original_name="Original entity name",
|
||||||
|
)
|
||||||
|
switch_entity_entry = registry.async_update_entity(
|
||||||
|
switch_entity_entry.entity_id,
|
||||||
|
config_entry_id=switch_config_entry.entry_id,
|
||||||
|
name="Custom entity name",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add the config entry
|
||||||
|
switch_as_x_config_entry = MockConfigEntry(
|
||||||
|
data={},
|
||||||
|
domain=DOMAIN,
|
||||||
|
options={
|
||||||
|
CONF_ENTITY_ID: switch_entity_entry.id,
|
||||||
|
CONF_TARGET_DOMAIN: target_domain,
|
||||||
|
},
|
||||||
|
title="ABC",
|
||||||
|
)
|
||||||
|
switch_as_x_config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
assert await hass.config_entries.async_setup(switch_as_x_config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
entity_entry = registry.async_get(
|
||||||
|
f"{target_domain}.device_name_original_entity_name"
|
||||||
|
)
|
||||||
|
assert entity_entry
|
||||||
|
assert entity_entry.device_id == switch_entity_entry.device_id
|
||||||
|
assert entity_entry.has_entity_name is True
|
||||||
|
assert entity_entry.name == "Custom entity name"
|
||||||
|
assert entity_entry.original_name == "Original entity name"
|
||||||
|
assert entity_entry.options == {
|
||||||
|
DOMAIN: {"entity_id": switch_entity_entry.entity_id}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("target_domain", PLATFORMS_TO_TEST)
|
||||||
|
async def test_custom_name_2(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
target_domain: Platform,
|
||||||
|
) -> None:
|
||||||
|
"""Test the source entity has a custom name.
|
||||||
|
|
||||||
|
This tests the custom name is only copied from the source device when the config
|
||||||
|
switch_as_x config entry is setup the first time.
|
||||||
|
"""
|
||||||
|
registry = er.async_get(hass)
|
||||||
|
device_registry = dr.async_get(hass)
|
||||||
|
|
||||||
|
switch_config_entry = MockConfigEntry()
|
||||||
|
|
||||||
|
device_entry = device_registry.async_get_or_create(
|
||||||
|
config_entry_id=switch_config_entry.entry_id,
|
||||||
|
connections={(dr.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
|
||||||
|
name="Device name",
|
||||||
|
)
|
||||||
|
|
||||||
|
switch_entity_entry = registry.async_get_or_create(
|
||||||
|
"switch",
|
||||||
|
"test",
|
||||||
|
"unique",
|
||||||
|
device_id=device_entry.id,
|
||||||
|
has_entity_name=True,
|
||||||
|
original_name="Original entity name",
|
||||||
|
)
|
||||||
|
switch_entity_entry = registry.async_update_entity(
|
||||||
|
switch_entity_entry.entity_id,
|
||||||
|
config_entry_id=switch_config_entry.entry_id,
|
||||||
|
name="New custom entity name",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add the config entry
|
||||||
|
switch_as_x_config_entry = MockConfigEntry(
|
||||||
|
data={},
|
||||||
|
domain=DOMAIN,
|
||||||
|
options={
|
||||||
|
CONF_ENTITY_ID: switch_entity_entry.id,
|
||||||
|
CONF_TARGET_DOMAIN: target_domain,
|
||||||
|
},
|
||||||
|
title="ABC",
|
||||||
|
)
|
||||||
|
switch_as_x_config_entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
switch_as_x_entity_entry = registry.async_get_or_create(
|
||||||
|
target_domain,
|
||||||
|
"switch_as_x",
|
||||||
|
switch_as_x_config_entry.entry_id,
|
||||||
|
suggested_object_id="device_name_original_entity_name",
|
||||||
|
)
|
||||||
|
switch_as_x_entity_entry = registry.async_update_entity(
|
||||||
|
switch_as_x_entity_entry.entity_id,
|
||||||
|
config_entry_id=switch_config_entry.entry_id,
|
||||||
|
name="Old custom entity name",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert await hass.config_entries.async_setup(switch_as_x_config_entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
entity_entry = registry.async_get(
|
||||||
|
f"{target_domain}.device_name_original_entity_name"
|
||||||
|
)
|
||||||
|
assert entity_entry
|
||||||
|
assert entity_entry.entity_id == switch_as_x_entity_entry.entity_id
|
||||||
|
assert entity_entry.device_id == switch_entity_entry.device_id
|
||||||
|
assert entity_entry.has_entity_name is True
|
||||||
|
assert entity_entry.name == "Old custom entity name"
|
||||||
|
assert entity_entry.original_name == "Original entity name"
|
||||||
|
assert entity_entry.options == {
|
||||||
|
DOMAIN: {"entity_id": switch_entity_entry.entity_id}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue