diff --git a/homeassistant/components/zha/entity.py b/homeassistant/components/zha/entity.py index c11cd405a99..108d8e27a9f 100644 --- a/homeassistant/components/zha/entity.py +++ b/homeassistant/components/zha/entity.py @@ -9,7 +9,6 @@ from homeassistant.helpers import entity from homeassistant.helpers.device_registry import CONNECTION_ZIGBEE from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.restore_state import RestoreEntity -from homeassistant.util import slugify from .core.const import ( ATTR_MANUFACTURER, @@ -38,17 +37,10 @@ class ZhaEntity(RestoreEntity, LogMixin, entity.Entity): self._force_update = False self._should_poll = False self._unique_id = unique_id - if not skip_entity_id: - ieee = zha_device.ieee - ieeetail = "".join([f"{o:02x}" for o in ieee[:4]]) - self.entity_id = "{}.{}_{}_{}_{}{}".format( - self._domain, - slugify(zha_device.manufacturer), - slugify(zha_device.model), - ieeetail, - channels[0].cluster.endpoint.endpoint_id, - kwargs.get(ENTITY_SUFFIX, ""), - ) + ieeetail = "".join([f"{o:02x}" for o in zha_device.ieee[:4]]) + ch_names = [ch.cluster.ep_attribute for ch in channels] + ch_names = ", ".join(sorted(ch_names)) + self._name = f"{zha_device.name} {ieeetail} {ch_names}" self._state = None self._device_state_attributes = {} self._zha_device = zha_device @@ -63,7 +55,7 @@ class ZhaEntity(RestoreEntity, LogMixin, entity.Entity): @property def name(self): """Return Entity's default name.""" - return self.zha_device.name + return self._name @property def unique_id(self) -> str: diff --git a/tests/components/zha/common.py b/tests/components/zha/common.py index 788faaaec73..583b4e0738b 100644 --- a/tests/components/zha/common.py +++ b/tests/components/zha/common.py @@ -161,23 +161,22 @@ async def async_setup_entry(hass, config_entry): return True -def make_entity_id(domain, device, cluster, use_suffix=True): - """Make the entity id for the entity under testing. +async def find_entity_id(domain, zha_device, hass): + """Find the entity id under the testing. This is used to get the entity id in order to get the state from the state machine so that we can test state changes. """ - ieee = device.ieee - ieeetail = "".join([f"{o:02x}" for o in ieee[:4]]) - entity_id = "{}.{}_{}_{}_{}{}".format( - domain, - slugify(device.manufacturer), - slugify(device.model), - ieeetail, - cluster.endpoint.endpoint_id, - ("", "_{}".format(cluster.cluster_id))[use_suffix], - ) - return entity_id + ieeetail = "".join([f"{o:02x}" for o in zha_device.ieee[:4]]) + head = f"{domain}." + slugify(f"{zha_device.name} {ieeetail}") + + enitiy_ids = hass.states.async_entity_ids(domain) + await hass.async_block_till_done() + + for entity_id in enitiy_ids: + if entity_id.startswith(head): + return entity_id + return None async def async_enable_traffic(hass, zha_gateway, zha_devices): @@ -188,7 +187,7 @@ async def async_enable_traffic(hass, zha_gateway, zha_devices): async def async_test_device_join( - hass, zha_gateway, cluster_id, domain, device_type=None + hass, zha_gateway, cluster_id, entity_id, device_type=None ): """Test a newly joining device. @@ -205,21 +204,15 @@ async def async_test_device_join( "zigpy.zcl.Cluster.bind", return_value=mock_coro([zcl_f.Status.SUCCESS, zcl_f.Status.SUCCESS]), ): - zigpy_device = await async_init_zigpy_device( + await async_init_zigpy_device( hass, [cluster_id, zigpy.zcl.clusters.general.Basic.cluster_id], [], device_type, zha_gateway, ieee="00:0d:6f:00:0a:90:69:f7", - manufacturer="FakeMan{}".format(cluster_id), - model="FakeMod{}".format(cluster_id), is_new_join=True, ) - cluster = zigpy_device.endpoints.get(1).in_clusters[cluster_id] - entity_id = make_entity_id( - domain, zigpy_device, cluster, use_suffix=device_type is None - ) assert hass.states.get(entity_id) is not None diff --git a/tests/components/zha/test_binary_sensor.py b/tests/components/zha/test_binary_sensor.py index 89dc1ae25a6..2765a465ace 100644 --- a/tests/components/zha/test_binary_sensor.py +++ b/tests/components/zha/test_binary_sensor.py @@ -11,8 +11,8 @@ from .common import ( async_enable_traffic, async_init_zigpy_device, async_test_device_join, + find_entity_id, make_attribute, - make_entity_id, make_zcl_header, ) @@ -27,6 +27,7 @@ async def test_binary_sensor(hass, config_entry, zha_gateway): [], None, zha_gateway, + ieee="00:0d:6f:11:9a:90:69:e6", ) zigpy_device_occupancy = await async_init_zigpy_device( @@ -46,15 +47,15 @@ async def test_binary_sensor(hass, config_entry, zha_gateway): # on off binary_sensor zone_cluster = zigpy_device_zone.endpoints.get(1).ias_zone - zone_entity_id = make_entity_id(DOMAIN, zigpy_device_zone, zone_cluster) zone_zha_device = zha_gateway.get_device(zigpy_device_zone.ieee) + zone_entity_id = await find_entity_id(DOMAIN, zone_zha_device, hass) + assert zone_entity_id is not None # occupancy binary_sensor occupancy_cluster = zigpy_device_occupancy.endpoints.get(1).occupancy - occupancy_entity_id = make_entity_id( - DOMAIN, zigpy_device_occupancy, occupancy_cluster - ) occupancy_zha_device = zha_gateway.get_device(zigpy_device_occupancy.ieee) + occupancy_entity_id = await find_entity_id(DOMAIN, occupancy_zha_device, hass) + assert occupancy_entity_id is not None # test that the sensors exist and are in the unavailable state assert hass.states.get(zone_entity_id).state == STATE_UNAVAILABLE @@ -76,7 +77,7 @@ async def test_binary_sensor(hass, config_entry, zha_gateway): # test new sensor join await async_test_device_join( - hass, zha_gateway, measurement.OccupancySensing.cluster_id, DOMAIN + hass, zha_gateway, measurement.OccupancySensing.cluster_id, occupancy_entity_id ) diff --git a/tests/components/zha/test_device_tracker.py b/tests/components/zha/test_device_tracker.py index 446920eb2f9..bac338ae5e0 100644 --- a/tests/components/zha/test_device_tracker.py +++ b/tests/components/zha/test_device_tracker.py @@ -16,8 +16,8 @@ from .common import ( async_enable_traffic, async_init_zigpy_device, async_test_device_join, + find_entity_id, make_attribute, - make_entity_id, make_zcl_header, ) @@ -47,8 +47,9 @@ async def test_device_tracker(hass, config_entry, zha_gateway): await hass.async_block_till_done() cluster = zigpy_device.endpoints.get(1).power - entity_id = make_entity_id(DOMAIN, zigpy_device, cluster, use_suffix=False) zha_device = zha_gateway.get_device(zigpy_device.ieee) + entity_id = await find_entity_id(DOMAIN, zha_device, hass) + assert entity_id is not None # test that the device tracker was created and that it is unavailable assert hass.states.get(entity_id).state == STATE_UNAVAILABLE @@ -90,6 +91,6 @@ async def test_device_tracker(hass, config_entry, zha_gateway): hass, zha_gateway, general.PowerConfiguration.cluster_id, - DOMAIN, + entity_id, SMARTTHINGS_ARRIVAL_SENSOR_DEVICE_TYPE, ) diff --git a/tests/components/zha/test_fan.py b/tests/components/zha/test_fan.py index a196ba50ba7..660bff2abac 100644 --- a/tests/components/zha/test_fan.py +++ b/tests/components/zha/test_fan.py @@ -20,8 +20,8 @@ from .common import ( async_enable_traffic, async_init_zigpy_device, async_test_device_join, + find_entity_id, make_attribute, - make_entity_id, make_zcl_header, ) @@ -41,8 +41,9 @@ async def test_fan(hass, config_entry, zha_gateway): await hass.async_block_till_done() cluster = zigpy_device.endpoints.get(1).fan - entity_id = make_entity_id(DOMAIN, zigpy_device, cluster) zha_device = zha_gateway.get_device(zigpy_device.ieee) + entity_id = await find_entity_id(DOMAIN, zha_device, hass) + assert entity_id is not None # test that the fan was created and that it is unavailable assert hass.states.get(entity_id).state == STATE_UNAVAILABLE @@ -97,7 +98,7 @@ async def test_fan(hass, config_entry, zha_gateway): assert cluster.write_attributes.call_args == call({"fan_mode": 3}) # test adding new fan to the network and HA - await async_test_device_join(hass, zha_gateway, hvac.Fan.cluster_id, DOMAIN) + await async_test_device_join(hass, zha_gateway, hvac.Fan.cluster_id, entity_id) async def async_turn_on(hass, entity_id, speed=None): diff --git a/tests/components/zha/test_light.py b/tests/components/zha/test_light.py index f0d9d4913e6..5180f8f976e 100644 --- a/tests/components/zha/test_light.py +++ b/tests/components/zha/test_light.py @@ -14,8 +14,8 @@ from .common import ( async_enable_traffic, async_init_zigpy_device, async_test_device_join, + find_entity_id, make_attribute, - make_entity_id, make_zcl_header, ) @@ -35,6 +35,7 @@ async def test_light(hass, config_entry, zha_gateway, monkeypatch): [], zigpy.profiles.zha.DeviceType.ON_OFF_LIGHT, zha_gateway, + ieee="00:0d:6f:11:0a:90:69:e6", ) zigpy_device_level = await async_init_zigpy_device( @@ -58,10 +59,9 @@ async def test_light(hass, config_entry, zha_gateway, monkeypatch): # on off light on_off_device_on_off_cluster = zigpy_device_on_off.endpoints.get(1).on_off - on_off_entity_id = make_entity_id( - DOMAIN, zigpy_device_on_off, on_off_device_on_off_cluster, use_suffix=False - ) on_off_zha_device = zha_gateway.get_device(zigpy_device_on_off.ieee) + on_off_entity_id = await find_entity_id(DOMAIN, on_off_zha_device, hass) + assert on_off_entity_id is not None # dimmable light level_device_on_off_cluster = zigpy_device_level.endpoints.get(1).on_off @@ -78,10 +78,9 @@ async def test_light(hass, config_entry, zha_gateway, monkeypatch): ) monkeypatch.setattr(level_device_on_off_cluster, "request", on_off_mock) monkeypatch.setattr(level_device_level_cluster, "request", level_mock) - level_entity_id = make_entity_id( - DOMAIN, zigpy_device_level, level_device_on_off_cluster, use_suffix=False - ) level_zha_device = zha_gateway.get_device(zigpy_device_level.ieee) + level_entity_id = await find_entity_id(DOMAIN, level_zha_device, hass) + assert level_entity_id is not None # test that the lights were created and that they are unavailable assert hass.states.get(on_off_entity_id).state == STATE_UNAVAILABLE @@ -125,7 +124,7 @@ async def test_light(hass, config_entry, zha_gateway, monkeypatch): hass, zha_gateway, general.OnOff.cluster_id, - DOMAIN, + on_off_entity_id, device_type=zigpy.profiles.zha.DeviceType.ON_OFF_LIGHT, ) diff --git a/tests/components/zha/test_lock.py b/tests/components/zha/test_lock.py index 118526a1d85..1daef317fed 100644 --- a/tests/components/zha/test_lock.py +++ b/tests/components/zha/test_lock.py @@ -11,8 +11,8 @@ from homeassistant.const import STATE_LOCKED, STATE_UNAVAILABLE, STATE_UNLOCKED from .common import ( async_enable_traffic, async_init_zigpy_device, + find_entity_id, make_attribute, - make_entity_id, make_zcl_header, ) @@ -39,8 +39,9 @@ async def test_lock(hass, config_entry, zha_gateway): await hass.async_block_till_done() cluster = zigpy_device.endpoints.get(1).door_lock - entity_id = make_entity_id(DOMAIN, zigpy_device, cluster) zha_device = zha_gateway.get_device(zigpy_device.ieee) + entity_id = await find_entity_id(DOMAIN, zha_device, hass) + assert entity_id is not None # test that the lock was created and that it is unavailable assert hass.states.get(entity_id).state == STATE_UNAVAILABLE diff --git a/tests/components/zha/test_sensor.py b/tests/components/zha/test_sensor.py index dec551f8d62..7746c5d422e 100644 --- a/tests/components/zha/test_sensor.py +++ b/tests/components/zha/test_sensor.py @@ -12,8 +12,8 @@ from .common import ( async_enable_traffic, async_init_zigpy_device, async_test_device_join, + find_entity_id, make_attribute, - make_entity_id, make_zcl_header, ) @@ -85,7 +85,7 @@ async def test_sensor(hass, config_entry, zha_gateway): # test joining a new temperature sensor to the network await async_test_device_join( - hass, zha_gateway, measurement.TemperatureMeasurement.cluster_id, DOMAIN + hass, zha_gateway, measurement.TemperatureMeasurement.cluster_id, entity_id ) @@ -110,7 +110,7 @@ async def async_build_devices(hass, zha_gateway, config_entry, cluster_ids): [], None, zha_gateway, - ieee="{}0:15:8d:00:02:32:4f:32".format(counter), + ieee="00:15:8d:00:02:32:4f:0{}".format(counter), manufacturer="Fake{}".format(cluster_id), model="FakeModel{}".format(cluster_id), ) @@ -126,10 +126,10 @@ async def async_build_devices(hass, zha_gateway, config_entry, cluster_ids): device_info = device_infos[cluster_id] zigpy_device = device_info["zigpy_device"] device_info["cluster"] = zigpy_device.endpoints.get(1).in_clusters[cluster_id] - device_info["entity_id"] = make_entity_id( - DOMAIN, zigpy_device, device_info["cluster"] - ) - device_info["zha_device"] = zha_gateway.get_device(zigpy_device.ieee) + zha_device = zha_gateway.get_device(zigpy_device.ieee) + device_info["zha_device"] = zha_device + device_info["entity_id"] = await find_entity_id(DOMAIN, zha_device, hass) + await hass.async_block_till_done() return device_infos diff --git a/tests/components/zha/test_switch.py b/tests/components/zha/test_switch.py index bf4ff3ed628..11a0b8f3481 100644 --- a/tests/components/zha/test_switch.py +++ b/tests/components/zha/test_switch.py @@ -11,8 +11,8 @@ from .common import ( async_enable_traffic, async_init_zigpy_device, async_test_device_join, + find_entity_id, make_attribute, - make_entity_id, make_zcl_header, ) @@ -39,8 +39,9 @@ async def test_switch(hass, config_entry, zha_gateway): await hass.async_block_till_done() cluster = zigpy_device.endpoints.get(1).on_off - entity_id = make_entity_id(DOMAIN, zigpy_device, cluster) zha_device = zha_gateway.get_device(zigpy_device.ieee) + entity_id = await find_entity_id(DOMAIN, zha_device, hass) + assert entity_id is not None # test that the switch was created and that its state is unavailable assert hass.states.get(entity_id).state == STATE_UNAVAILABLE @@ -93,4 +94,4 @@ async def test_switch(hass, config_entry, zha_gateway): ) # test joining a new switch to the network and HA - await async_test_device_join(hass, zha_gateway, general.OnOff.cluster_id, DOMAIN) + await async_test_device_join(hass, zha_gateway, general.OnOff.cluster_id, entity_id)