From 1e64d830ac5dfb9a1e23121a269cf9fa73e9d226 Mon Sep 17 00:00:00 2001 From: Guido Schmitz Date: Tue, 22 Nov 2022 09:54:05 +0100 Subject: [PATCH] Migrate devolo Home Control to new entity naming (#74969) --- .../devolo_home_control/binary_sensor.py | 16 +++++---- .../devolo_home_control/devolo_device.py | 14 +++++--- .../components/devolo_home_control/sensor.py | 9 ++--- .../devolo_home_control/test_binary_sensor.py | 35 ++++++++++++------- .../devolo_home_control/test_climate.py | 8 ++++- .../devolo_home_control/test_cover.py | 2 ++ .../devolo_home_control/test_light.py | 2 ++ .../devolo_home_control/test_siren.py | 8 ++++- 8 files changed, 62 insertions(+), 32 deletions(-) diff --git a/homeassistant/components/devolo_home_control/binary_sensor.py b/homeassistant/components/devolo_home_control/binary_sensor.py index a6b18c2b312..e8395062e8c 100644 --- a/homeassistant/components/devolo_home_control/binary_sensor.py +++ b/homeassistant/components/devolo_home_control/binary_sensor.py @@ -81,13 +81,14 @@ class DevoloBinaryDeviceEntity(DevoloDeviceEntity, BinarySensorEntity): or self._binary_sensor_property.sensor_type ) - if self._attr_device_class is None: - if device_instance.binary_sensor_property[element_uid].sub_type != "": - self._attr_name += ( - f" {device_instance.binary_sensor_property[element_uid].sub_type}" - ) - else: - self._attr_name += f" {device_instance.binary_sensor_property[element_uid].sensor_type}" + if device_instance.binary_sensor_property[element_uid].sub_type != "": + self._attr_name = device_instance.binary_sensor_property[ + element_uid + ].sub_type.capitalize() + else: + self._attr_name = device_instance.binary_sensor_property[ + element_uid + ].sensor_type.capitalize() self._value = self._binary_sensor_property.state @@ -128,6 +129,7 @@ class DevoloRemoteControl(DevoloDeviceEntity, BinarySensorEntity): self._key = key self._attr_is_on = False + self._attr_name = f"Button {key}" def _sync(self, message: tuple) -> None: """Update the binary sensor state.""" diff --git a/homeassistant/components/devolo_home_control/devolo_device.py b/homeassistant/components/devolo_home_control/devolo_device.py index 6087e07799d..5848f682626 100644 --- a/homeassistant/components/devolo_home_control/devolo_device.py +++ b/homeassistant/components/devolo_home_control/devolo_device.py @@ -19,6 +19,8 @@ _LOGGER = logging.getLogger(__name__) class DevoloDeviceEntity(Entity): """Abstract representation of a device within devolo Home Control.""" + _attr_has_entity_name = True + def __init__( self, homecontrol: HomeControl, device_instance: Zwave, element_uid: str ) -> None: @@ -29,9 +31,6 @@ class DevoloDeviceEntity(Entity): self._attr_available = ( device_instance.is_online() ) # This is not doing I/O. It fetches an internal state of the API - self._attr_name: str = device_instance.settings_property[ - "general_device_settings" - ].name self._attr_should_poll = False self._attr_unique_id = element_uid self._attr_device_info = DeviceInfo( @@ -39,7 +38,7 @@ class DevoloDeviceEntity(Entity): identifiers={(DOMAIN, self._device_instance.uid)}, manufacturer=device_instance.brand, model=device_instance.name, - name=self._attr_name, + name=device_instance.settings_property["general_device_settings"].name, suggested_area=device_instance.settings_property[ "general_device_settings" ].zone, @@ -47,11 +46,16 @@ class DevoloDeviceEntity(Entity): self.subscriber: Subscriber | None = None self.sync_callback = self._sync + self._value: float async def async_added_to_hass(self) -> None: """Call when entity is added to hass.""" - self.subscriber = Subscriber(self._attr_name, callback=self.sync_callback) + assert self.device_info + assert self.device_info["name"] # The name was set on entity creation + self.subscriber = Subscriber( + self.device_info["name"], callback=self.sync_callback + ) self._homecontrol.publisher.register( self._device_instance.uid, self.subscriber, self.sync_callback ) diff --git a/homeassistant/components/devolo_home_control/sensor.py b/homeassistant/components/devolo_home_control/sensor.py index 2d023d23e2d..33a17929f71 100644 --- a/homeassistant/components/devolo_home_control/sensor.py +++ b/homeassistant/components/devolo_home_control/sensor.py @@ -115,12 +115,9 @@ class DevoloGenericMultiLevelDeviceEntity(DevoloMultiLevelDeviceEntity): self._multi_level_sensor_property.sensor_type ) self._attr_native_unit_of_measurement = self._multi_level_sensor_property.unit - + self._attr_name = self._multi_level_sensor_property.sensor_type.capitalize() self._value = self._multi_level_sensor_property.value - if self._attr_device_class is None: - self._attr_name += f" {self._multi_level_sensor_property.sensor_type}" - if element_uid.startswith("devolo.VoltageMultiLevelSensor:"): self._attr_entity_registry_enabled_default = False @@ -143,7 +140,7 @@ class DevoloBatteryEntity(DevoloMultiLevelDeviceEntity): self._attr_state_class = STATE_CLASS_MAPPING.get("battery") self._attr_entity_category = EntityCategory.DIAGNOSTIC self._attr_native_unit_of_measurement = PERCENTAGE - + self._attr_name = "Battery level" self._value = device_instance.battery_level @@ -179,7 +176,7 @@ class DevoloConsumptionEntity(DevoloMultiLevelDeviceEntity): device_instance.consumption_property[element_uid], consumption ) - self._attr_name += f" {consumption}" + self._attr_name = f"{consumption.capitalize()} consumption" @property def unique_id(self) -> str: diff --git a/tests/components/devolo_home_control/test_binary_sensor.py b/tests/components/devolo_home_control/test_binary_sensor.py index 4bce2ebd19e..ec8a7d288ab 100644 --- a/tests/components/devolo_home_control/test_binary_sensor.py +++ b/tests/components/devolo_home_control/test_binary_sensor.py @@ -4,7 +4,12 @@ from unittest.mock import patch import pytest from homeassistant.components.binary_sensor import DOMAIN -from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE +from homeassistant.const import ( + ATTR_FRIENDLY_NAME, + STATE_OFF, + STATE_ON, + STATE_UNAVAILABLE, +) from homeassistant.core import HomeAssistant from homeassistant.helpers import entity_registry from homeassistant.helpers.entity import EntityCategory @@ -31,25 +36,30 @@ async def test_binary_sensor(hass: HomeAssistant): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - state = hass.states.get(f"{DOMAIN}.test") + state = hass.states.get(f"{DOMAIN}.test_door") assert state is not None assert state.state == STATE_OFF + assert state.attributes[ATTR_FRIENDLY_NAME] == "Test Door" - state = hass.states.get(f"{DOMAIN}.test_2") + state = hass.states.get(f"{DOMAIN}.test_overload") assert state is not None + assert state.attributes[ATTR_FRIENDLY_NAME] == "Test Overload" er = entity_registry.async_get(hass) - assert er.async_get(f"{DOMAIN}.test_2").entity_category == EntityCategory.DIAGNOSTIC + assert ( + er.async_get(f"{DOMAIN}.test_overload").entity_category + == EntityCategory.DIAGNOSTIC + ) # Emulate websocket message: sensor turned on test_gateway.publisher.dispatch("Test", ("Test", True)) await hass.async_block_till_done() - assert hass.states.get(f"{DOMAIN}.test").state == STATE_ON + assert hass.states.get(f"{DOMAIN}.test_door").state == STATE_ON # Emulate websocket message: device went offline test_gateway.devices["Test"].status = 1 test_gateway.publisher.dispatch("Test", ("Status", False, "status")) await hass.async_block_till_done() - assert hass.states.get(f"{DOMAIN}.test").state == STATE_UNAVAILABLE + assert hass.states.get(f"{DOMAIN}.test_door").state == STATE_UNAVAILABLE @pytest.mark.usefixtures("mock_zeroconf") @@ -65,25 +75,26 @@ async def test_remote_control(hass: HomeAssistant): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - state = hass.states.get(f"{DOMAIN}.test") + state = hass.states.get(f"{DOMAIN}.test_button_1") assert state is not None assert state.state == STATE_OFF + assert state.attributes[ATTR_FRIENDLY_NAME] == "Test Button 1" # Emulate websocket message: button pressed test_gateway.publisher.dispatch("Test", ("Test", 1)) await hass.async_block_till_done() - assert hass.states.get(f"{DOMAIN}.test").state == STATE_ON + assert hass.states.get(f"{DOMAIN}.test_button_1").state == STATE_ON # Emulate websocket message: button released test_gateway.publisher.dispatch("Test", ("Test", 0)) await hass.async_block_till_done() - assert hass.states.get(f"{DOMAIN}.test").state == STATE_OFF + assert hass.states.get(f"{DOMAIN}.test_button_1").state == STATE_OFF # Emulate websocket message: device went offline test_gateway.devices["Test"].status = 1 test_gateway.publisher.dispatch("Test", ("Status", False, "status")) await hass.async_block_till_done() - assert hass.states.get(f"{DOMAIN}.test").state == STATE_UNAVAILABLE + assert hass.states.get(f"{DOMAIN}.test_button_1").state == STATE_UNAVAILABLE @pytest.mark.usefixtures("mock_zeroconf") @@ -97,7 +108,7 @@ async def test_disabled(hass: HomeAssistant): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - assert hass.states.get(f"{DOMAIN}.devolo.WarningBinaryFI:Test") is None + assert hass.states.get(f"{DOMAIN}.test_door") is None @pytest.mark.usefixtures("mock_zeroconf") @@ -112,7 +123,7 @@ async def test_remove_from_hass(hass: HomeAssistant): await hass.config_entries.async_setup(entry.entry_id) await hass.async_block_till_done() - state = hass.states.get(f"{DOMAIN}.test") + state = hass.states.get(f"{DOMAIN}.test_door") assert state is not None await hass.config_entries.async_remove(entry.entry_id) await hass.async_block_till_done() diff --git a/tests/components/devolo_home_control/test_climate.py b/tests/components/devolo_home_control/test_climate.py index 98200b66476..c1ecc7ecc29 100644 --- a/tests/components/devolo_home_control/test_climate.py +++ b/tests/components/devolo_home_control/test_climate.py @@ -7,7 +7,12 @@ from homeassistant.components.climate import ( SERVICE_SET_TEMPERATURE, HVACMode, ) -from homeassistant.const import ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_UNAVAILABLE +from homeassistant.const import ( + ATTR_ENTITY_ID, + ATTR_FRIENDLY_NAME, + ATTR_TEMPERATURE, + STATE_UNAVAILABLE, +) from homeassistant.core import HomeAssistant from . import configure_integration @@ -30,6 +35,7 @@ async def test_climate(hass: HomeAssistant): assert state is not None assert state.state == HVACMode.HEAT assert state.attributes[ATTR_TEMPERATURE] == test_gateway.devices["Test"].value + assert state.attributes[ATTR_FRIENDLY_NAME] == "Test" # Emulate websocket message: temperature changed test_gateway.publisher.dispatch("Test", ("Test", 21.0)) diff --git a/tests/components/devolo_home_control/test_cover.py b/tests/components/devolo_home_control/test_cover.py index 1c05c00370b..a783b635001 100644 --- a/tests/components/devolo_home_control/test_cover.py +++ b/tests/components/devolo_home_control/test_cover.py @@ -4,6 +4,7 @@ from unittest.mock import patch from homeassistant.components.cover import ATTR_CURRENT_POSITION, ATTR_POSITION, DOMAIN from homeassistant.const import ( ATTR_ENTITY_ID, + ATTR_FRIENDLY_NAME, SERVICE_CLOSE_COVER, SERVICE_OPEN_COVER, SERVICE_SET_COVER_POSITION, @@ -32,6 +33,7 @@ async def test_cover(hass: HomeAssistant): state = hass.states.get(f"{DOMAIN}.test") assert state is not None assert state.state == STATE_OPEN + assert state.attributes[ATTR_FRIENDLY_NAME] == "Test" assert ( state.attributes[ATTR_CURRENT_POSITION] == test_gateway.devices["Test"] diff --git a/tests/components/devolo_home_control/test_light.py b/tests/components/devolo_home_control/test_light.py index 7b18b28a493..ce4a42f5226 100644 --- a/tests/components/devolo_home_control/test_light.py +++ b/tests/components/devolo_home_control/test_light.py @@ -10,6 +10,7 @@ from homeassistant.components.light import ( ) from homeassistant.const import ( ATTR_ENTITY_ID, + ATTR_FRIENDLY_NAME, SERVICE_TURN_OFF, SERVICE_TURN_ON, STATE_OFF, @@ -36,6 +37,7 @@ async def test_light_without_binary_sensor(hass: HomeAssistant): state = hass.states.get(f"{DOMAIN}.test") assert state is not None assert state.state == STATE_ON + assert state.attributes[ATTR_FRIENDLY_NAME] == "Test" assert state.attributes[ATTR_COLOR_MODE] == ColorMode.BRIGHTNESS assert state.attributes[ATTR_SUPPORTED_COLOR_MODES] == [ColorMode.BRIGHTNESS] assert state.attributes[ATTR_BRIGHTNESS] == round( diff --git a/tests/components/devolo_home_control/test_siren.py b/tests/components/devolo_home_control/test_siren.py index 97e044738a5..bca54a5b5b8 100644 --- a/tests/components/devolo_home_control/test_siren.py +++ b/tests/components/devolo_home_control/test_siren.py @@ -4,7 +4,12 @@ from unittest.mock import patch import pytest from homeassistant.components.siren import DOMAIN -from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE +from homeassistant.const import ( + ATTR_FRIENDLY_NAME, + STATE_OFF, + STATE_ON, + STATE_UNAVAILABLE, +) from homeassistant.core import HomeAssistant from . import configure_integration @@ -27,6 +32,7 @@ async def test_siren(hass: HomeAssistant): state = hass.states.get(f"{DOMAIN}.test") assert state is not None assert state.state == STATE_OFF + assert state.attributes[ATTR_FRIENDLY_NAME] == "Test" # Emulate websocket message: sensor turned on test_gateway.publisher.dispatch("Test", ("devolo.SirenMultiLevelSwitch:Test", 1))