mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 04:07:08 +00:00
Add and cleanup tplink translations (#135120)
This commit is contained in:
parent
15e785b974
commit
0d9ac25257
@ -6,7 +6,7 @@ import asyncio
|
|||||||
from collections.abc import Iterable
|
from collections.abc import Iterable
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any, cast
|
||||||
|
|
||||||
from aiohttp import ClientSession
|
from aiohttp import ClientSession
|
||||||
from kasa import (
|
from kasa import (
|
||||||
@ -178,9 +178,23 @@ async def async_setup_entry(hass: HomeAssistant, entry: TPLinkConfigEntry) -> bo
|
|||||||
if not credentials and entry_credentials_hash:
|
if not credentials and entry_credentials_hash:
|
||||||
data = {k: v for k, v in entry.data.items() if k != CONF_CREDENTIALS_HASH}
|
data = {k: v for k, v in entry.data.items() if k != CONF_CREDENTIALS_HASH}
|
||||||
hass.config_entries.async_update_entry(entry, data=data)
|
hass.config_entries.async_update_entry(entry, data=data)
|
||||||
raise ConfigEntryAuthFailed from ex
|
raise ConfigEntryAuthFailed(
|
||||||
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="device_authentication",
|
||||||
|
translation_placeholders={
|
||||||
|
"func": "connect",
|
||||||
|
"exc": str(ex),
|
||||||
|
},
|
||||||
|
) from ex
|
||||||
except KasaException as ex:
|
except KasaException as ex:
|
||||||
raise ConfigEntryNotReady from ex
|
raise ConfigEntryNotReady(
|
||||||
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="device_error",
|
||||||
|
translation_placeholders={
|
||||||
|
"func": "connect",
|
||||||
|
"exc": str(ex),
|
||||||
|
},
|
||||||
|
) from ex
|
||||||
|
|
||||||
device_credentials_hash = device.credentials_hash
|
device_credentials_hash = device.credentials_hash
|
||||||
|
|
||||||
@ -212,7 +226,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: TPLinkConfigEntry) -> bo
|
|||||||
# wait for the next discovery to find the device at its new address
|
# wait for the next discovery to find the device at its new address
|
||||||
# and update the config entry so we do not mix up devices.
|
# and update the config entry so we do not mix up devices.
|
||||||
raise ConfigEntryNotReady(
|
raise ConfigEntryNotReady(
|
||||||
f"Unexpected device found at {host}; expected {entry.unique_id}, found {found_mac}"
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="unexpected_device",
|
||||||
|
translation_placeholders={
|
||||||
|
"host": host,
|
||||||
|
# all entries have a unique id
|
||||||
|
"expected": cast(str, entry.unique_id),
|
||||||
|
"found": found_mac,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
parent_coordinator = TPLinkDataUpdateCoordinator(hass, device, timedelta(seconds=5))
|
parent_coordinator = TPLinkDataUpdateCoordinator(hass, device, timedelta(seconds=5))
|
||||||
@ -263,7 +284,7 @@ def legacy_device_id(device: Device) -> str:
|
|||||||
return device_id.split("_")[1]
|
return device_id.split("_")[1]
|
||||||
|
|
||||||
|
|
||||||
def get_device_name(device: Device, parent: Device | None = None) -> str:
|
def get_device_name(device: Device, parent: Device | None = None) -> str | None:
|
||||||
"""Get a name for the device. alias can be none on some devices."""
|
"""Get a name for the device. alias can be none on some devices."""
|
||||||
if device.alias:
|
if device.alias:
|
||||||
return device.alias
|
return device.alias
|
||||||
@ -278,7 +299,7 @@ def get_device_name(device: Device, parent: Device | None = None) -> str:
|
|||||||
]
|
]
|
||||||
suffix = f" {devices.index(device.device_id) + 1}" if len(devices) > 1 else ""
|
suffix = f" {devices.index(device.device_id) + 1}" if len(devices) > 1 else ""
|
||||||
return f"{device.device_type.value.capitalize()}{suffix}"
|
return f"{device.device_type.value.capitalize()}{suffix}"
|
||||||
return f"Unnamed {device.model}"
|
return None
|
||||||
|
|
||||||
|
|
||||||
async def get_credentials(hass: HomeAssistant) -> Credentials | None:
|
async def get_credentials(hass: HomeAssistant) -> Credentials | None:
|
||||||
|
@ -42,11 +42,6 @@ BINARY_SENSOR_DESCRIPTIONS: Final = (
|
|||||||
key="cloud_connection",
|
key="cloud_connection",
|
||||||
device_class=BinarySensorDeviceClass.CONNECTIVITY,
|
device_class=BinarySensorDeviceClass.CONNECTIVITY,
|
||||||
),
|
),
|
||||||
# To be replaced & disabled per default by the upcoming update platform.
|
|
||||||
TPLinkBinarySensorEntityDescription(
|
|
||||||
key="update_available",
|
|
||||||
device_class=BinarySensorDeviceClass.UPDATE,
|
|
||||||
),
|
|
||||||
TPLinkBinarySensorEntityDescription(
|
TPLinkBinarySensorEntityDescription(
|
||||||
key="temperature_warning",
|
key="temperature_warning",
|
||||||
),
|
),
|
||||||
|
@ -21,7 +21,7 @@ from homeassistant.exceptions import ServiceValidationError
|
|||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
from . import TPLinkConfigEntry
|
from . import TPLinkConfigEntry
|
||||||
from .const import UNIT_MAPPING
|
from .const import DOMAIN, UNIT_MAPPING
|
||||||
from .coordinator import TPLinkDataUpdateCoordinator
|
from .coordinator import TPLinkDataUpdateCoordinator
|
||||||
from .entity import CoordinatedTPLinkEntity, async_refresh_after
|
from .entity import CoordinatedTPLinkEntity, async_refresh_after
|
||||||
|
|
||||||
@ -104,7 +104,13 @@ class TPLinkClimateEntity(CoordinatedTPLinkEntity, ClimateEntity):
|
|||||||
elif hvac_mode is HVACMode.OFF:
|
elif hvac_mode is HVACMode.OFF:
|
||||||
await self._state_feature.set_value(False)
|
await self._state_feature.set_value(False)
|
||||||
else:
|
else:
|
||||||
raise ServiceValidationError(f"Tried to set unsupported mode: {hvac_mode}")
|
raise ServiceValidationError(
|
||||||
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="unsupported_mode",
|
||||||
|
translation_placeholders={
|
||||||
|
"mode": hvac_mode,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
@async_refresh_after
|
@async_refresh_after
|
||||||
async def async_turn_on(self) -> None:
|
async def async_turn_on(self) -> None:
|
||||||
|
@ -162,6 +162,9 @@ class CoordinatedTPLinkEntity(CoordinatorEntity[TPLinkDataUpdateCoordinator], AB
|
|||||||
|
|
||||||
registry_device = device
|
registry_device = device
|
||||||
device_name = get_device_name(device, parent=parent)
|
device_name = get_device_name(device, parent=parent)
|
||||||
|
translation_key: str | None = None
|
||||||
|
translation_placeholders: Mapping[str, str] | None = None
|
||||||
|
|
||||||
if parent and parent.device_type is not Device.Type.Hub:
|
if parent and parent.device_type is not Device.Type.Hub:
|
||||||
if not feature or feature.id == PRIMARY_STATE_ID:
|
if not feature or feature.id == PRIMARY_STATE_ID:
|
||||||
# Entity will be added to parent if not a hub and no feature
|
# Entity will be added to parent if not a hub and no feature
|
||||||
@ -169,6 +172,9 @@ class CoordinatedTPLinkEntity(CoordinatorEntity[TPLinkDataUpdateCoordinator], AB
|
|||||||
# is the primary state
|
# is the primary state
|
||||||
registry_device = parent
|
registry_device = parent
|
||||||
device_name = get_device_name(registry_device)
|
device_name = get_device_name(registry_device)
|
||||||
|
if not device_name:
|
||||||
|
translation_key = "unnamed_device"
|
||||||
|
translation_placeholders = {"model": parent.model}
|
||||||
else:
|
else:
|
||||||
# Prefix the device name with the parent name unless it is a
|
# Prefix the device name with the parent name unless it is a
|
||||||
# hub attached device. Sensible default for child devices like
|
# hub attached device. Sensible default for child devices like
|
||||||
@ -177,13 +183,28 @@ class CoordinatedTPLinkEntity(CoordinatorEntity[TPLinkDataUpdateCoordinator], AB
|
|||||||
# Bedroom Ceiling Fan; Child device aliases will be Ceiling Fan
|
# Bedroom Ceiling Fan; Child device aliases will be Ceiling Fan
|
||||||
# and Dimmer Switch for both so should be distinguished by the
|
# and Dimmer Switch for both so should be distinguished by the
|
||||||
# parent name.
|
# parent name.
|
||||||
device_name = f"{get_device_name(parent)} {get_device_name(device, parent=parent)}"
|
parent_device_name = get_device_name(parent)
|
||||||
|
child_device_name = get_device_name(device, parent=parent)
|
||||||
|
if parent_device_name:
|
||||||
|
device_name = f"{parent_device_name} {child_device_name}"
|
||||||
|
else:
|
||||||
|
device_name = None
|
||||||
|
translation_key = "unnamed_device"
|
||||||
|
translation_placeholders = {
|
||||||
|
"model": f"{parent.model} {child_device_name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
if device_name is None and not translation_key:
|
||||||
|
translation_key = "unnamed_device"
|
||||||
|
translation_placeholders = {"model": device.model}
|
||||||
|
|
||||||
self._attr_device_info = DeviceInfo(
|
self._attr_device_info = DeviceInfo(
|
||||||
identifiers={(DOMAIN, str(registry_device.device_id))},
|
identifiers={(DOMAIN, str(registry_device.device_id))},
|
||||||
manufacturer="TP-Link",
|
manufacturer="TP-Link",
|
||||||
model=registry_device.model,
|
model=registry_device.model,
|
||||||
name=device_name,
|
name=device_name,
|
||||||
|
translation_key=translation_key,
|
||||||
|
translation_placeholders=translation_placeholders,
|
||||||
sw_version=registry_device.hw_info["sw_ver"],
|
sw_version=registry_device.hw_info["sw_ver"],
|
||||||
hw_version=registry_device.hw_info["hw_ver"],
|
hw_version=registry_device.hw_info["hw_ver"],
|
||||||
)
|
)
|
||||||
@ -320,6 +341,7 @@ class CoordinatedTPLinkFeatureEntity(CoordinatedTPLinkEntity, ABC):
|
|||||||
|
|
||||||
if descriptions and (desc := descriptions.get(feature.id)):
|
if descriptions and (desc := descriptions.get(feature.id)):
|
||||||
translation_key: str | None = feature.id
|
translation_key: str | None = feature.id
|
||||||
|
|
||||||
# HA logic is to name entities based on the following logic:
|
# HA logic is to name entities based on the following logic:
|
||||||
# _attr_name > translation.name > description.name
|
# _attr_name > translation.name > description.name
|
||||||
# > device_class (if base platform supports).
|
# > device_class (if base platform supports).
|
||||||
|
@ -125,12 +125,6 @@
|
|||||||
"signal_level": {
|
"signal_level": {
|
||||||
"default": "mdi:signal"
|
"default": "mdi:signal"
|
||||||
},
|
},
|
||||||
"current_firmware_version": {
|
|
||||||
"default": "mdi:information"
|
|
||||||
},
|
|
||||||
"available_firmware_version": {
|
|
||||||
"default": "mdi:information-outline"
|
|
||||||
},
|
|
||||||
"alarm_source": {
|
"alarm_source": {
|
||||||
"default": "mdi:bell"
|
"default": "mdi:bell"
|
||||||
},
|
},
|
||||||
|
@ -116,11 +116,6 @@ SENSOR_DESCRIPTIONS: tuple[TPLinkSensorEntityDescription, ...] = (
|
|||||||
TPLinkSensorEntityDescription(
|
TPLinkSensorEntityDescription(
|
||||||
key="alarm_source",
|
key="alarm_source",
|
||||||
),
|
),
|
||||||
TPLinkSensorEntityDescription(
|
|
||||||
key="temperature",
|
|
||||||
device_class=SensorDeviceClass.TEMPERATURE,
|
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
SENSOR_DESCRIPTIONS_MAP = {desc.key: desc for desc in SENSOR_DESCRIPTIONS}
|
SENSOR_DESCRIPTIONS_MAP = {desc.key: desc for desc in SENSOR_DESCRIPTIONS}
|
||||||
|
@ -109,26 +109,9 @@
|
|||||||
"overheated": {
|
"overheated": {
|
||||||
"name": "Overheated"
|
"name": "Overheated"
|
||||||
},
|
},
|
||||||
"battery_low": {
|
|
||||||
"name": "Battery low"
|
|
||||||
},
|
|
||||||
"cloud_connection": {
|
"cloud_connection": {
|
||||||
"name": "Cloud connection"
|
"name": "Cloud connection"
|
||||||
},
|
},
|
||||||
"update_available": {
|
|
||||||
"name": "[%key:component::binary_sensor::entity_component::update::name%]",
|
|
||||||
"state": {
|
|
||||||
"off": "[%key:component::binary_sensor::entity_component::update::state::off%]",
|
|
||||||
"on": "[%key:component::binary_sensor::entity_component::update::state::on%]"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"is_open": {
|
|
||||||
"name": "[%key:component::binary_sensor::entity_component::door::name%]",
|
|
||||||
"state": {
|
|
||||||
"off": "[%key:common::state::closed%]",
|
|
||||||
"on": "[%key:common::state::open%]"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"water_alert": {
|
"water_alert": {
|
||||||
"name": "[%key:component::binary_sensor::entity_component::moisture::name%]",
|
"name": "[%key:component::binary_sensor::entity_component::moisture::name%]",
|
||||||
"state": {
|
"state": {
|
||||||
@ -195,27 +178,6 @@
|
|||||||
"signal_level": {
|
"signal_level": {
|
||||||
"name": "Signal level"
|
"name": "Signal level"
|
||||||
},
|
},
|
||||||
"current_firmware_version": {
|
|
||||||
"name": "Current firmware version"
|
|
||||||
},
|
|
||||||
"available_firmware_version": {
|
|
||||||
"name": "Available firmware version"
|
|
||||||
},
|
|
||||||
"battery_level": {
|
|
||||||
"name": "Battery level"
|
|
||||||
},
|
|
||||||
"temperature": {
|
|
||||||
"name": "[%key:component::sensor::entity_component::temperature::name%]"
|
|
||||||
},
|
|
||||||
"voltage": {
|
|
||||||
"name": "[%key:component::sensor::entity_component::voltage::name%]"
|
|
||||||
},
|
|
||||||
"current": {
|
|
||||||
"name": "[%key:component::sensor::entity_component::current::name%]"
|
|
||||||
},
|
|
||||||
"humidity": {
|
|
||||||
"name": "[%key:component::sensor::entity_component::humidity::name%]"
|
|
||||||
},
|
|
||||||
"device_time": {
|
"device_time": {
|
||||||
"name": "Device time"
|
"name": "Device time"
|
||||||
},
|
},
|
||||||
@ -230,9 +192,6 @@
|
|||||||
},
|
},
|
||||||
"alarm_source": {
|
"alarm_source": {
|
||||||
"name": "Alarm source"
|
"name": "Alarm source"
|
||||||
},
|
|
||||||
"rssi": {
|
|
||||||
"name": "[%key:component::sensor::entity_component::signal_strength::name%]"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"switch": {
|
"switch": {
|
||||||
@ -291,6 +250,11 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"device": {
|
||||||
|
"unnamed_device": {
|
||||||
|
"name": "Unnamed {model}"
|
||||||
|
}
|
||||||
|
},
|
||||||
"services": {
|
"services": {
|
||||||
"sequence_effect": {
|
"sequence_effect": {
|
||||||
"name": "Sequence effect",
|
"name": "Sequence effect",
|
||||||
@ -397,6 +361,12 @@
|
|||||||
},
|
},
|
||||||
"set_custom_effect": {
|
"set_custom_effect": {
|
||||||
"message": "Error trying to set custom effect {effect}: {exc}"
|
"message": "Error trying to set custom effect {effect}: {exc}"
|
||||||
|
},
|
||||||
|
"unexpected_device": {
|
||||||
|
"message": "Unexpected device found at {host}; expected {expected}, found {found}"
|
||||||
|
},
|
||||||
|
"unsupported_mode": {
|
||||||
|
"message": "Tried to set unsupported mode: {mode}"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"issues": {
|
"issues": {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# serializer version: 1
|
# serializer version: 1
|
||||||
# name: test_states[binary_sensor.my_device_battery_low-entry]
|
# name: test_states[binary_sensor.my_device_battery-entry]
|
||||||
EntityRegistryEntrySnapshot({
|
EntityRegistryEntrySnapshot({
|
||||||
'aliases': set({
|
'aliases': set({
|
||||||
}),
|
}),
|
||||||
@ -11,7 +11,7 @@
|
|||||||
'disabled_by': <RegistryEntryDisabler.INTEGRATION: 'integration'>,
|
'disabled_by': <RegistryEntryDisabler.INTEGRATION: 'integration'>,
|
||||||
'domain': 'binary_sensor',
|
'domain': 'binary_sensor',
|
||||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||||
'entity_id': 'binary_sensor.my_device_battery_low',
|
'entity_id': 'binary_sensor.my_device_battery',
|
||||||
'has_entity_name': True,
|
'has_entity_name': True,
|
||||||
'hidden_by': None,
|
'hidden_by': None,
|
||||||
'icon': None,
|
'icon': None,
|
||||||
@ -23,7 +23,7 @@
|
|||||||
}),
|
}),
|
||||||
'original_device_class': <BinarySensorDeviceClass.BATTERY: 'battery'>,
|
'original_device_class': <BinarySensorDeviceClass.BATTERY: 'battery'>,
|
||||||
'original_icon': None,
|
'original_icon': None,
|
||||||
'original_name': 'Battery low',
|
'original_name': 'Battery',
|
||||||
'platform': 'tplink',
|
'platform': 'tplink',
|
||||||
'previous_unique_id': None,
|
'previous_unique_id': None,
|
||||||
'supported_features': 0,
|
'supported_features': 0,
|
||||||
|
@ -115,7 +115,7 @@
|
|||||||
'state': '2024-06-24T09:03:11+00:00',
|
'state': '2024-06-24T09:03:11+00:00',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
# name: test_states[sensor.my_device_battery_level-entry]
|
# name: test_states[sensor.my_device_battery-entry]
|
||||||
EntityRegistryEntrySnapshot({
|
EntityRegistryEntrySnapshot({
|
||||||
'aliases': set({
|
'aliases': set({
|
||||||
}),
|
}),
|
||||||
@ -129,7 +129,7 @@
|
|||||||
'disabled_by': None,
|
'disabled_by': None,
|
||||||
'domain': 'sensor',
|
'domain': 'sensor',
|
||||||
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
'entity_category': <EntityCategory.DIAGNOSTIC: 'diagnostic'>,
|
||||||
'entity_id': 'sensor.my_device_battery_level',
|
'entity_id': 'sensor.my_device_battery',
|
||||||
'has_entity_name': True,
|
'has_entity_name': True,
|
||||||
'hidden_by': None,
|
'hidden_by': None,
|
||||||
'icon': None,
|
'icon': None,
|
||||||
@ -141,7 +141,7 @@
|
|||||||
}),
|
}),
|
||||||
'original_device_class': <SensorDeviceClass.BATTERY: 'battery'>,
|
'original_device_class': <SensorDeviceClass.BATTERY: 'battery'>,
|
||||||
'original_icon': None,
|
'original_icon': None,
|
||||||
'original_name': 'Battery level',
|
'original_name': 'Battery',
|
||||||
'platform': 'tplink',
|
'platform': 'tplink',
|
||||||
'previous_unique_id': None,
|
'previous_unique_id': None,
|
||||||
'supported_features': 0,
|
'supported_features': 0,
|
||||||
@ -150,16 +150,16 @@
|
|||||||
'unit_of_measurement': '%',
|
'unit_of_measurement': '%',
|
||||||
})
|
})
|
||||||
# ---
|
# ---
|
||||||
# name: test_states[sensor.my_device_battery_level-state]
|
# name: test_states[sensor.my_device_battery-state]
|
||||||
StateSnapshot({
|
StateSnapshot({
|
||||||
'attributes': ReadOnlyDict({
|
'attributes': ReadOnlyDict({
|
||||||
'device_class': 'battery',
|
'device_class': 'battery',
|
||||||
'friendly_name': 'my_device Battery level',
|
'friendly_name': 'my_device Battery',
|
||||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||||
'unit_of_measurement': '%',
|
'unit_of_measurement': '%',
|
||||||
}),
|
}),
|
||||||
'context': <ANY>,
|
'context': <ANY>,
|
||||||
'entity_id': 'sensor.my_device_battery_level',
|
'entity_id': 'sensor.my_device_battery',
|
||||||
'last_changed': <ANY>,
|
'last_changed': <ANY>,
|
||||||
'last_reported': <ANY>,
|
'last_reported': <ANY>,
|
||||||
'last_updated': <ANY>,
|
'last_updated': <ANY>,
|
||||||
|
@ -260,7 +260,9 @@ async def test_strip_unique_ids(
|
|||||||
|
|
||||||
|
|
||||||
async def test_strip_blank_alias(
|
async def test_strip_blank_alias(
|
||||||
hass: HomeAssistant, entity_registry: er.EntityRegistry
|
hass: HomeAssistant,
|
||||||
|
entity_registry: er.EntityRegistry,
|
||||||
|
device_registry: dr.DeviceRegistry,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test a strip unique id."""
|
"""Test a strip unique id."""
|
||||||
already_migrated_config_entry = MockConfigEntry(
|
already_migrated_config_entry = MockConfigEntry(
|
||||||
@ -277,11 +279,27 @@ async def test_strip_blank_alias(
|
|||||||
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}})
|
await async_setup_component(hass, tplink.DOMAIN, {tplink.DOMAIN: {}})
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
strip_entity_id = "switch.unnamed_ks123"
|
||||||
|
state = hass.states.get(strip_entity_id)
|
||||||
|
assert state.name == "Unnamed KS123"
|
||||||
|
reg_ent = entity_registry.async_get(strip_entity_id)
|
||||||
|
assert reg_ent
|
||||||
|
reg_dev = device_registry.async_get(reg_ent.device_id)
|
||||||
|
assert reg_dev
|
||||||
|
assert reg_dev.name == "Unnamed KS123"
|
||||||
|
|
||||||
for plug_id in range(2):
|
for plug_id in range(2):
|
||||||
entity_id = f"switch.unnamed_ks123_stripsocket_{plug_id + 1}"
|
entity_id = f"switch.unnamed_ks123_stripsocket_{plug_id + 1}"
|
||||||
state = hass.states.get(entity_id)
|
state = hass.states.get(entity_id)
|
||||||
assert state.name == f"Unnamed KS123 Stripsocket {plug_id + 1}"
|
assert state.name == f"Unnamed KS123 Stripsocket {plug_id + 1}"
|
||||||
|
|
||||||
|
reg_ent = entity_registry.async_get(entity_id)
|
||||||
|
assert reg_ent
|
||||||
|
reg_dev = device_registry.async_get(reg_ent.device_id)
|
||||||
|
assert reg_dev
|
||||||
|
# Switch is a primary feature so entities go on the parent device.
|
||||||
|
assert reg_dev.name == "Unnamed KS123"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("exception_type", "msg", "reauth_expected"),
|
("exception_type", "msg", "reauth_expected"),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user