Don't set entity_id in ZHA entities (#28362)

* Don't set entity_id on ZHA entities.
* Update tests.
* Use comma as separator for multiple channel names.
* Address PR comments.
This commit is contained in:
Alexei Chetroi 2019-10-31 12:31:06 -04:00 committed by GitHub
parent d133501735
commit 89213a4ce8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 55 additions and 66 deletions

View File

@ -9,7 +9,6 @@ from homeassistant.helpers import entity
from homeassistant.helpers.device_registry import CONNECTION_ZIGBEE from homeassistant.helpers.device_registry import CONNECTION_ZIGBEE
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.restore_state import RestoreEntity from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.util import slugify
from .core.const import ( from .core.const import (
ATTR_MANUFACTURER, ATTR_MANUFACTURER,
@ -38,17 +37,10 @@ class ZhaEntity(RestoreEntity, LogMixin, entity.Entity):
self._force_update = False self._force_update = False
self._should_poll = False self._should_poll = False
self._unique_id = unique_id self._unique_id = unique_id
if not skip_entity_id: ieeetail = "".join([f"{o:02x}" for o in zha_device.ieee[:4]])
ieee = zha_device.ieee ch_names = [ch.cluster.ep_attribute for ch in channels]
ieeetail = "".join([f"{o:02x}" for o in ieee[:4]]) ch_names = ", ".join(sorted(ch_names))
self.entity_id = "{}.{}_{}_{}_{}{}".format( self._name = f"{zha_device.name} {ieeetail} {ch_names}"
self._domain,
slugify(zha_device.manufacturer),
slugify(zha_device.model),
ieeetail,
channels[0].cluster.endpoint.endpoint_id,
kwargs.get(ENTITY_SUFFIX, ""),
)
self._state = None self._state = None
self._device_state_attributes = {} self._device_state_attributes = {}
self._zha_device = zha_device self._zha_device = zha_device
@ -63,7 +55,7 @@ class ZhaEntity(RestoreEntity, LogMixin, entity.Entity):
@property @property
def name(self): def name(self):
"""Return Entity's default name.""" """Return Entity's default name."""
return self.zha_device.name return self._name
@property @property
def unique_id(self) -> str: def unique_id(self) -> str:

View File

@ -161,23 +161,22 @@ async def async_setup_entry(hass, config_entry):
return True return True
def make_entity_id(domain, device, cluster, use_suffix=True): async def find_entity_id(domain, zha_device, hass):
"""Make the entity id for the entity under testing. """Find the entity id under the testing.
This is used to get the entity id in order to get the state from the state 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. machine so that we can test state changes.
""" """
ieee = device.ieee ieeetail = "".join([f"{o:02x}" for o in zha_device.ieee[:4]])
ieeetail = "".join([f"{o:02x}" for o in ieee[:4]]) head = f"{domain}." + slugify(f"{zha_device.name} {ieeetail}")
entity_id = "{}.{}_{}_{}_{}{}".format(
domain, enitiy_ids = hass.states.async_entity_ids(domain)
slugify(device.manufacturer), await hass.async_block_till_done()
slugify(device.model),
ieeetail, for entity_id in enitiy_ids:
cluster.endpoint.endpoint_id, if entity_id.startswith(head):
("", "_{}".format(cluster.cluster_id))[use_suffix], return entity_id
) return None
return entity_id
async def async_enable_traffic(hass, zha_gateway, zha_devices): 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( 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. """Test a newly joining device.
@ -205,21 +204,15 @@ async def async_test_device_join(
"zigpy.zcl.Cluster.bind", "zigpy.zcl.Cluster.bind",
return_value=mock_coro([zcl_f.Status.SUCCESS, zcl_f.Status.SUCCESS]), 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, hass,
[cluster_id, zigpy.zcl.clusters.general.Basic.cluster_id], [cluster_id, zigpy.zcl.clusters.general.Basic.cluster_id],
[], [],
device_type, device_type,
zha_gateway, zha_gateway,
ieee="00:0d:6f:00:0a:90:69:f7", ieee="00:0d:6f:00:0a:90:69:f7",
manufacturer="FakeMan{}".format(cluster_id),
model="FakeMod{}".format(cluster_id),
is_new_join=True, 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 assert hass.states.get(entity_id) is not None

View File

@ -11,8 +11,8 @@ from .common import (
async_enable_traffic, async_enable_traffic,
async_init_zigpy_device, async_init_zigpy_device,
async_test_device_join, async_test_device_join,
find_entity_id,
make_attribute, make_attribute,
make_entity_id,
make_zcl_header, make_zcl_header,
) )
@ -27,6 +27,7 @@ async def test_binary_sensor(hass, config_entry, zha_gateway):
[], [],
None, None,
zha_gateway, zha_gateway,
ieee="00:0d:6f:11:9a:90:69:e6",
) )
zigpy_device_occupancy = await async_init_zigpy_device( 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 # on off binary_sensor
zone_cluster = zigpy_device_zone.endpoints.get(1).ias_zone 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_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 binary_sensor
occupancy_cluster = zigpy_device_occupancy.endpoints.get(1).occupancy 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_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 # test that the sensors exist and are in the unavailable state
assert hass.states.get(zone_entity_id).state == STATE_UNAVAILABLE 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 # test new sensor join
await async_test_device_join( await async_test_device_join(
hass, zha_gateway, measurement.OccupancySensing.cluster_id, DOMAIN hass, zha_gateway, measurement.OccupancySensing.cluster_id, occupancy_entity_id
) )

View File

@ -16,8 +16,8 @@ from .common import (
async_enable_traffic, async_enable_traffic,
async_init_zigpy_device, async_init_zigpy_device,
async_test_device_join, async_test_device_join,
find_entity_id,
make_attribute, make_attribute,
make_entity_id,
make_zcl_header, make_zcl_header,
) )
@ -47,8 +47,9 @@ async def test_device_tracker(hass, config_entry, zha_gateway):
await hass.async_block_till_done() await hass.async_block_till_done()
cluster = zigpy_device.endpoints.get(1).power 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) 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 # test that the device tracker was created and that it is unavailable
assert hass.states.get(entity_id).state == STATE_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, hass,
zha_gateway, zha_gateway,
general.PowerConfiguration.cluster_id, general.PowerConfiguration.cluster_id,
DOMAIN, entity_id,
SMARTTHINGS_ARRIVAL_SENSOR_DEVICE_TYPE, SMARTTHINGS_ARRIVAL_SENSOR_DEVICE_TYPE,
) )

View File

@ -20,8 +20,8 @@ from .common import (
async_enable_traffic, async_enable_traffic,
async_init_zigpy_device, async_init_zigpy_device,
async_test_device_join, async_test_device_join,
find_entity_id,
make_attribute, make_attribute,
make_entity_id,
make_zcl_header, make_zcl_header,
) )
@ -41,8 +41,9 @@ async def test_fan(hass, config_entry, zha_gateway):
await hass.async_block_till_done() await hass.async_block_till_done()
cluster = zigpy_device.endpoints.get(1).fan 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) 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 # test that the fan was created and that it is unavailable
assert hass.states.get(entity_id).state == STATE_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}) assert cluster.write_attributes.call_args == call({"fan_mode": 3})
# test adding new fan to the network and HA # 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): async def async_turn_on(hass, entity_id, speed=None):

View File

@ -14,8 +14,8 @@ from .common import (
async_enable_traffic, async_enable_traffic,
async_init_zigpy_device, async_init_zigpy_device,
async_test_device_join, async_test_device_join,
find_entity_id,
make_attribute, make_attribute,
make_entity_id,
make_zcl_header, make_zcl_header,
) )
@ -35,6 +35,7 @@ async def test_light(hass, config_entry, zha_gateway, monkeypatch):
[], [],
zigpy.profiles.zha.DeviceType.ON_OFF_LIGHT, zigpy.profiles.zha.DeviceType.ON_OFF_LIGHT,
zha_gateway, zha_gateway,
ieee="00:0d:6f:11:0a:90:69:e6",
) )
zigpy_device_level = await async_init_zigpy_device( 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 light
on_off_device_on_off_cluster = zigpy_device_on_off.endpoints.get(1).on_off 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_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 # dimmable light
level_device_on_off_cluster = zigpy_device_level.endpoints.get(1).on_off 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_on_off_cluster, "request", on_off_mock)
monkeypatch.setattr(level_device_level_cluster, "request", level_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_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 # test that the lights were created and that they are unavailable
assert hass.states.get(on_off_entity_id).state == STATE_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, hass,
zha_gateway, zha_gateway,
general.OnOff.cluster_id, general.OnOff.cluster_id,
DOMAIN, on_off_entity_id,
device_type=zigpy.profiles.zha.DeviceType.ON_OFF_LIGHT, device_type=zigpy.profiles.zha.DeviceType.ON_OFF_LIGHT,
) )

View File

@ -11,8 +11,8 @@ from homeassistant.const import STATE_LOCKED, STATE_UNAVAILABLE, STATE_UNLOCKED
from .common import ( from .common import (
async_enable_traffic, async_enable_traffic,
async_init_zigpy_device, async_init_zigpy_device,
find_entity_id,
make_attribute, make_attribute,
make_entity_id,
make_zcl_header, make_zcl_header,
) )
@ -39,8 +39,9 @@ async def test_lock(hass, config_entry, zha_gateway):
await hass.async_block_till_done() await hass.async_block_till_done()
cluster = zigpy_device.endpoints.get(1).door_lock 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) 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 # test that the lock was created and that it is unavailable
assert hass.states.get(entity_id).state == STATE_UNAVAILABLE assert hass.states.get(entity_id).state == STATE_UNAVAILABLE

View File

@ -12,8 +12,8 @@ from .common import (
async_enable_traffic, async_enable_traffic,
async_init_zigpy_device, async_init_zigpy_device,
async_test_device_join, async_test_device_join,
find_entity_id,
make_attribute, make_attribute,
make_entity_id,
make_zcl_header, 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 # test joining a new temperature sensor to the network
await async_test_device_join( 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, None,
zha_gateway, 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), manufacturer="Fake{}".format(cluster_id),
model="FakeModel{}".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] device_info = device_infos[cluster_id]
zigpy_device = device_info["zigpy_device"] zigpy_device = device_info["zigpy_device"]
device_info["cluster"] = zigpy_device.endpoints.get(1).in_clusters[cluster_id] device_info["cluster"] = zigpy_device.endpoints.get(1).in_clusters[cluster_id]
device_info["entity_id"] = make_entity_id( zha_device = zha_gateway.get_device(zigpy_device.ieee)
DOMAIN, zigpy_device, device_info["cluster"] device_info["zha_device"] = zha_device
) device_info["entity_id"] = await find_entity_id(DOMAIN, zha_device, hass)
device_info["zha_device"] = zha_gateway.get_device(zigpy_device.ieee) await hass.async_block_till_done()
return device_infos return device_infos

View File

@ -11,8 +11,8 @@ from .common import (
async_enable_traffic, async_enable_traffic,
async_init_zigpy_device, async_init_zigpy_device,
async_test_device_join, async_test_device_join,
find_entity_id,
make_attribute, make_attribute,
make_entity_id,
make_zcl_header, make_zcl_header,
) )
@ -39,8 +39,9 @@ async def test_switch(hass, config_entry, zha_gateway):
await hass.async_block_till_done() await hass.async_block_till_done()
cluster = zigpy_device.endpoints.get(1).on_off 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) 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 # test that the switch was created and that its state is unavailable
assert hass.states.get(entity_id).state == STATE_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 # 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)