diff --git a/homeassistant/components/zha/alarm_control_panel.py b/homeassistant/components/zha/alarm_control_panel.py index dfb19ac3bad..b6794e909d8 100644 --- a/homeassistant/components/zha/alarm_control_panel.py +++ b/homeassistant/components/zha/alarm_control_panel.py @@ -81,6 +81,7 @@ async def async_setup_entry( class ZHAAlarmControlPanel(ZhaEntity, AlarmControlPanelEntity): """Entity for ZHA alarm control devices.""" + _attr_name: str = "Alarm control panel" _attr_code_format = CodeFormat.TEXT _attr_supported_features = ( AlarmControlPanelEntityFeature.ARM_HOME diff --git a/homeassistant/components/zha/binary_sensor.py b/homeassistant/components/zha/binary_sensor.py index d7b81832c2e..6b080db081e 100644 --- a/homeassistant/components/zha/binary_sensor.py +++ b/homeassistant/components/zha/binary_sensor.py @@ -33,13 +33,22 @@ from .core.registries import ZHA_ENTITIES from .entity import ZhaEntity # Zigbee Cluster Library Zone Type to Home Assistant device class -CLASS_MAPPING = { - 0x000D: BinarySensorDeviceClass.MOTION, - 0x0015: BinarySensorDeviceClass.OPENING, - 0x0028: BinarySensorDeviceClass.SMOKE, - 0x002A: BinarySensorDeviceClass.MOISTURE, - 0x002B: BinarySensorDeviceClass.GAS, - 0x002D: BinarySensorDeviceClass.VIBRATION, +IAS_ZONE_CLASS_MAPPING = { + IasZone.ZoneType.Motion_Sensor: BinarySensorDeviceClass.MOTION, + IasZone.ZoneType.Contact_Switch: BinarySensorDeviceClass.OPENING, + IasZone.ZoneType.Fire_Sensor: BinarySensorDeviceClass.SMOKE, + IasZone.ZoneType.Water_Sensor: BinarySensorDeviceClass.MOISTURE, + IasZone.ZoneType.Carbon_Monoxide_Sensor: BinarySensorDeviceClass.GAS, + IasZone.ZoneType.Vibration_Movement_Sensor: BinarySensorDeviceClass.VIBRATION, +} + +IAS_ZONE_NAME_MAPPING = { + IasZone.ZoneType.Motion_Sensor: "Motion", + IasZone.ZoneType.Contact_Switch: "Opening", + IasZone.ZoneType.Fire_Sensor: "Smoke", + IasZone.ZoneType.Water_Sensor: "Moisture", + IasZone.ZoneType.Carbon_Monoxide_Sensor: "Gas", + IasZone.ZoneType.Vibration_Movement_Sensor: "Vibration", } STRICT_MATCH = functools.partial(ZHA_ENTITIES.strict_match, Platform.BINARY_SENSOR) @@ -108,6 +117,7 @@ class Accelerometer(BinarySensor): """ZHA BinarySensor.""" SENSOR_ATTR = "acceleration" + _attr_name: str = "Accelerometer" _attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.MOVING @@ -116,6 +126,7 @@ class Occupancy(BinarySensor): """ZHA BinarySensor.""" SENSOR_ATTR = "occupancy" + _attr_name: str = "Occupancy" _attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.OCCUPANCY @@ -124,6 +135,7 @@ class Opening(BinarySensor): """ZHA OnOff BinarySensor.""" SENSOR_ATTR = "on_off" + _attr_name: str = "Opening" _attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.OPENING # Client/out cluster attributes aren't stored in the zigpy database, but are properly stored in the runtime cache. @@ -142,6 +154,7 @@ class BinaryInput(BinarySensor): """ZHA BinarySensor.""" SENSOR_ATTR = "present_value" + _attr_name: str = "Binary input" @STRICT_MATCH( @@ -159,6 +172,7 @@ class BinaryInput(BinarySensor): class Motion(Opening): """ZHA OnOff BinarySensor with motion device class.""" + _attr_name: str = "Motion" _attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.MOTION @@ -168,10 +182,17 @@ class IASZone(BinarySensor): SENSOR_ATTR = "zone_status" + @property + def name(self) -> str | None: + """Return the name of the sensor.""" + zone_type = self._cluster_handler.cluster.get("zone_type") + return IAS_ZONE_NAME_MAPPING.get(zone_type, "iaszone") + @property def device_class(self) -> BinarySensorDeviceClass | None: """Return device class from component DEVICE_CLASSES.""" - return CLASS_MAPPING.get(self._cluster_handler.cluster.get("zone_type")) + zone_type = self._cluster_handler.cluster.get("zone_type") + return IAS_ZONE_CLASS_MAPPING.get(zone_type) @staticmethod def parse(value: bool | int) -> bool: @@ -220,6 +241,7 @@ class FrostLock(BinarySensor, id_suffix="frost_lock"): SENSOR_ATTR = "frost_lock" _attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.LOCK + _attr_name: str = "Frost lock" @MULTI_MATCH(cluster_handler_names="ikea_airpurifier") @@ -228,6 +250,7 @@ class ReplaceFilter(BinarySensor, id_suffix="replace_filter"): SENSOR_ATTR = "replace_filter" _attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.PROBLEM + _attr_name: str = "Replace filter" @MULTI_MATCH(cluster_handler_names="opple_cluster", models={"aqara.feeder.acn001"}) diff --git a/homeassistant/components/zha/climate.py b/homeassistant/components/zha/climate.py index fa4dd968c6e..9f999bd52fa 100644 --- a/homeassistant/components/zha/climate.py +++ b/homeassistant/components/zha/climate.py @@ -139,6 +139,7 @@ class Thermostat(ZhaEntity, ClimateEntity): _attr_precision = PRECISION_TENTHS _attr_temperature_unit = UnitOfTemperature.CELSIUS + _attr_name: str = "Thermostat" def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs): """Initialize ZHA Thermostat instance.""" diff --git a/homeassistant/components/zha/cover.py b/homeassistant/components/zha/cover.py index f26fcef5295..fce37904126 100644 --- a/homeassistant/components/zha/cover.py +++ b/homeassistant/components/zha/cover.py @@ -71,6 +71,8 @@ async def async_setup_entry( class ZhaCover(ZhaEntity, CoverEntity): """Representation of a ZHA cover.""" + _attr_name: str = "Cover" + def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs): """Init this sensor.""" super().__init__(unique_id, zha_device, cluster_handlers, **kwargs) @@ -197,6 +199,7 @@ class Shade(ZhaEntity, CoverEntity): """ZHA Shade.""" _attr_device_class = CoverDeviceClass.SHADE + _attr_name: str = "Shade" def __init__( self, @@ -308,6 +311,8 @@ class Shade(ZhaEntity, CoverEntity): class KeenVent(Shade): """Keen vent cover.""" + _attr_name: str = "Keen vent" + _attr_device_class = CoverDeviceClass.DAMPER async def async_open_cover(self, **kwargs: Any) -> None: diff --git a/homeassistant/components/zha/device_tracker.py b/homeassistant/components/zha/device_tracker.py index 83843802fe1..d473eadeebe 100644 --- a/homeassistant/components/zha/device_tracker.py +++ b/homeassistant/components/zha/device_tracker.py @@ -49,6 +49,7 @@ class ZHADeviceScannerEntity(ScannerEntity, ZhaEntity): """Represent a tracked device.""" _attr_should_poll = True # BaseZhaEntity defaults to False + _attr_name: str = "Device scanner" def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs): """Initialize the ZHA device tracker.""" diff --git a/homeassistant/components/zha/entity.py b/homeassistant/components/zha/entity.py index cfcbadb3d83..97258a77e2b 100644 --- a/homeassistant/components/zha/entity.py +++ b/homeassistant/components/zha/entity.py @@ -52,7 +52,6 @@ class BaseZhaEntity(LogMixin, entity.Entity): def __init__(self, unique_id: str, zha_device: ZHADevice, **kwargs: Any) -> None: """Init ZHA entity.""" - self._name: str = "" self._unique_id: str = unique_id if self.unique_id_suffix: self._unique_id += f"-{self.unique_id_suffix}" @@ -62,13 +61,6 @@ class BaseZhaEntity(LogMixin, entity.Entity): self._unsubs: list[Callable[[], None]] = [] self.remove_future: asyncio.Future[Any] = asyncio.Future() - @property - def name(self) -> str: - """Return Entity's default name.""" - if hasattr(self, "_attr_name") and self._attr_name is not None: - return self._attr_name - return self._name - @property def unique_id(self) -> str: """Return a unique ID.""" @@ -167,13 +159,7 @@ class ZhaEntity(BaseZhaEntity, RestoreEntity): ) -> None: """Init ZHA entity.""" super().__init__(unique_id, zha_device, **kwargs) - self._name: str = ( - self.__class__.__name__.lower() - .replace("zha", "") - .replace("entity", "") - .replace("sensor", "") - .capitalize() - ) + self.cluster_handlers: dict[str, ClusterHandler] = {} for cluster_handler in cluster_handlers: self.cluster_handlers[cluster_handler.name] = cluster_handler @@ -249,6 +235,9 @@ class ZhaEntity(BaseZhaEntity, RestoreEntity): class ZhaGroupEntity(BaseZhaEntity): """A base class for ZHA group entities.""" + # The group name is set in the initializer + _attr_name: str + def __init__( self, entity_ids: list[str], @@ -261,9 +250,6 @@ class ZhaGroupEntity(BaseZhaEntity): super().__init__(unique_id, zha_device, **kwargs) self._available = False self._group = zha_device.gateway.groups.get(group_id) - self._name = ( - f"{self._group.name}_zha_group_0x{group_id:04x}".lower().capitalize() - ) self._group_id: int = group_id self._entity_ids: list[str] = entity_ids self._async_unsub_state_changed: CALLBACK_TYPE | None = None @@ -271,6 +257,8 @@ class ZhaGroupEntity(BaseZhaEntity): self._change_listener_debouncer: Debouncer | None = None self._update_group_from_child_delay = DEFAULT_UPDATE_GROUP_FROM_CHILD_DELAY + self._attr_name = self._group.name + @property def available(self) -> bool: """Return entity availability.""" diff --git a/homeassistant/components/zha/fan.py b/homeassistant/components/zha/fan.py index 8325f1a3b69..82725accfa4 100644 --- a/homeassistant/components/zha/fan.py +++ b/homeassistant/components/zha/fan.py @@ -136,6 +136,8 @@ class BaseFan(FanEntity): class ZhaFan(BaseFan, ZhaEntity): """Representation of a ZHA fan.""" + _attr_name: str = "Fan" + def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs): """Init this sensor.""" super().__init__(unique_id, zha_device, cluster_handlers, **kwargs) @@ -263,6 +265,8 @@ IKEA_PRESET_MODES = list(IKEA_NAME_TO_PRESET_MODE) class IkeaFan(BaseFan, ZhaEntity): """Representation of a ZHA fan.""" + _attr_name: str = "IKEA fan" + def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs): """Init this sensor.""" super().__init__(unique_id, zha_device, cluster_handlers, **kwargs) diff --git a/homeassistant/components/zha/light.py b/homeassistant/components/zha/light.py index 05f03f7631e..3d3412784f7 100644 --- a/homeassistant/components/zha/light.py +++ b/homeassistant/components/zha/light.py @@ -637,6 +637,7 @@ class BaseLight(LogMixin, light.LightEntity): class Light(BaseLight, ZhaEntity): """Representation of a ZHA or ZLL light.""" + _attr_name: str = "Light" _attr_supported_color_modes: set[ColorMode] _REFRESH_INTERVAL = (45, 75) @@ -1065,6 +1066,7 @@ class Light(BaseLight, ZhaEntity): class HueLight(Light): """Representation of a HUE light which does not report attributes.""" + _attr_name: str = "Light" _REFRESH_INTERVAL = (3, 5) @@ -1076,6 +1078,7 @@ class HueLight(Light): class ForceOnLight(Light): """Representation of a light which does not respect move_to_level_with_on_off.""" + _attr_name: str = "Light" _FORCE_ON = True @@ -1087,6 +1090,7 @@ class ForceOnLight(Light): class MinTransitionLight(Light): """Representation of a light which does not react to any "move to" calls with 0 as a transition.""" + _attr_name: str = "Light" _DEFAULT_MIN_TRANSITION_TIME = 1 diff --git a/homeassistant/components/zha/lock.py b/homeassistant/components/zha/lock.py index e97bb036324..2f6bce0b20e 100644 --- a/homeassistant/components/zha/lock.py +++ b/homeassistant/components/zha/lock.py @@ -96,6 +96,8 @@ async def async_setup_entry( class ZhaDoorLock(ZhaEntity, LockEntity): """Representation of a ZHA lock.""" + _attr_name: str = "Door lock" + def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs): """Init this sensor.""" super().__init__(unique_id, zha_device, cluster_handlers, **kwargs) diff --git a/homeassistant/components/zha/number.py b/homeassistant/components/zha/number.py index 7c07d2704a9..6bc6f30a34f 100644 --- a/homeassistant/components/zha/number.py +++ b/homeassistant/components/zha/number.py @@ -279,6 +279,8 @@ async def async_setup_entry( class ZhaNumber(ZhaEntity, NumberEntity): """Representation of a ZHA Number entity.""" + _attr_name: str = "Number" + def __init__( self, unique_id: str, @@ -331,7 +333,7 @@ class ZhaNumber(ZhaEntity, NumberEntity): return super().native_step @property - def name(self) -> str: + def name(self) -> str | None: """Return the name of the number entity.""" description = self._analog_output_cluster_handler.description if description is not None and len(description) > 0: diff --git a/homeassistant/components/zha/sensor.py b/homeassistant/components/zha/sensor.py index e4a2c5384a1..dda9412b56f 100644 --- a/homeassistant/components/zha/sensor.py +++ b/homeassistant/components/zha/sensor.py @@ -191,6 +191,7 @@ class AnalogInput(Sensor): """Sensor that displays analog input values.""" SENSOR_ATTR = "present_value" + _attr_name: str = "Analog input" @MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_POWER_CONFIGURATION) diff --git a/homeassistant/components/zha/siren.py b/homeassistant/components/zha/siren.py index 043df779dca..a4c699d515b 100644 --- a/homeassistant/components/zha/siren.py +++ b/homeassistant/components/zha/siren.py @@ -74,6 +74,8 @@ async def async_setup_entry( class ZHASiren(ZhaEntity, SirenEntity): """Representation of a ZHA siren.""" + _attr_name: str = "Siren" + def __init__( self, unique_id: str, diff --git a/homeassistant/components/zha/switch.py b/homeassistant/components/zha/switch.py index 9e2714ffaba..99db68760a8 100644 --- a/homeassistant/components/zha/switch.py +++ b/homeassistant/components/zha/switch.py @@ -64,6 +64,8 @@ async def async_setup_entry( class Switch(ZhaEntity, SwitchEntity): """ZHA switch.""" + _attr_name: str = "Switch" + def __init__( self, unique_id: str, @@ -286,6 +288,7 @@ class OnOffWindowDetectionFunctionConfigurationEntity( _zcl_attribute: str = "window_detection_function" _zcl_inverter_attribute: str = "window_detection_function_inverter" + _attr_name: str = "Invert window detection" @CONFIG_DIAGNOSTIC_MATCH( diff --git a/tests/components/zha/common.py b/tests/components/zha/common.py index cae67f8d768..d3f3bf9b654 100644 --- a/tests/components/zha/common.py +++ b/tests/components/zha/common.py @@ -167,7 +167,9 @@ def find_entity_ids(domain, zha_device, hass): def async_find_group_entity_id(hass, domain, group): """Find the group entity id under test.""" - entity_id = f"{domain}.fakemanufacturer_fakemodel_{group.name.lower().replace(' ','_')}_zha_group_0x{group.group_id:04x}" + entity_id = ( + f"{domain}.fakemanufacturer_fakemodel_{group.name.lower().replace(' ', '_')}" + ) entity_ids = hass.states.async_entity_ids(domain) diff --git a/tests/components/zha/conftest.py b/tests/components/zha/conftest.py index d734ec22fad..8e31b45afd8 100644 --- a/tests/components/zha/conftest.py +++ b/tests/components/zha/conftest.py @@ -199,6 +199,7 @@ def zigpy_device_mock(zigpy_app_controller): nwk=0xB79C, patch_cluster=True, quirk=None, + attributes=None, ): """Make a fake device using the specified cluster classes.""" device = zigpy.device.Device( diff --git a/tests/components/zha/test_discover.py b/tests/components/zha/test_discover.py index d00199f0851..236a3c4ad86 100644 --- a/tests/components/zha/test_discover.py +++ b/tests/components/zha/test_discover.py @@ -36,6 +36,7 @@ import homeassistant.helpers.entity_registry as er from .common import get_zha_gateway from .conftest import SIG_EP_INPUT, SIG_EP_OUTPUT, SIG_EP_PROFILE, SIG_EP_TYPE from .zha_devices_list import ( + DEV_SIG_ATTRIBUTES, DEV_SIG_CLUSTER_HANDLERS, DEV_SIG_ENT_MAP, DEV_SIG_ENT_MAP_CLASS, @@ -89,11 +90,12 @@ async def test_devices( entity_registry = er.async_get(hass_disable_services) zigpy_device = zigpy_device_mock( - device[SIG_ENDPOINTS], - "00:11:22:33:44:55:66:77", - device[SIG_MANUFACTURER], - device[SIG_MODEL], + endpoints=device[SIG_ENDPOINTS], + ieee="00:11:22:33:44:55:66:77", + manufacturer=device[SIG_MANUFACTURER], + model=device[SIG_MODEL], node_descriptor=device[SIG_NODE_DESC], + attributes=device.get(DEV_SIG_ATTRIBUTES), patch_cluster=False, ) diff --git a/tests/components/zha/test_registries.py b/tests/components/zha/test_registries.py index 1ab8e331b0b..057921f80a9 100644 --- a/tests/components/zha/test_registries.py +++ b/tests/components/zha/test_registries.py @@ -1,14 +1,21 @@ """Test ZHA registries.""" +from __future__ import annotations + import importlib import inspect +import typing from unittest import mock import pytest import zhaquirks +from homeassistant.components.zha.binary_sensor import IASZone import homeassistant.components.zha.core.registries as registries from homeassistant.helpers import entity_registry as er +if typing.TYPE_CHECKING: + from homeassistant.components.zha.core.entity import ZhaEntity + MANUFACTURER = "mock manufacturer" MODEL = "mock model" QUIRK_CLASS = "mock.class" @@ -521,6 +528,24 @@ def test_multi_sensor_match( } +def iter_all_rules() -> typing.Iterable[registries.MatchRule, list[type[ZhaEntity]]]: + """Iterate over all match rules and their corresponding entities.""" + + for rules in registries.ZHA_ENTITIES._strict_registry.values(): + for rule, entity in rules.items(): + yield rule, [entity] + + for rules in registries.ZHA_ENTITIES._multi_entity_registry.values(): + for multi in rules.values(): + for rule, entities in multi.items(): + yield rule, entities + + for rules in registries.ZHA_ENTITIES._config_diagnostic_entity_registry.values(): + for multi in rules.values(): + for rule, entities in multi.items(): + yield rule, entities + + def test_quirk_classes() -> None: """Make sure that quirk_classes in components matches are valid.""" @@ -552,16 +577,18 @@ def test_quirk_classes() -> None: if not find_quirk_class(zhaquirks, quirk_tok[0], quirk_tok[1]): raise ValueError(f"Quirk class '{value}' does not exists.") - for component in registries.ZHA_ENTITIES._strict_registry.items(): - for rule in component[1].items(): - quirk_class_validator(rule[0].quirk_classes) + for rule, _ in iter_all_rules(): + quirk_class_validator(rule.quirk_classes) - for component in registries.ZHA_ENTITIES._multi_entity_registry.items(): - for item in component[1].items(): - for rule in item[1].items(): - quirk_class_validator(rule[0].quirk_classes) - for component in registries.ZHA_ENTITIES._config_diagnostic_entity_registry.items(): - for item in component[1].items(): - for rule in item[1].items(): - quirk_class_validator(rule[0].quirk_classes) +def test_entity_names() -> None: + """Make sure that all handlers expose entities with valid names.""" + + for _, entities in iter_all_rules(): + for entity in entities: + if hasattr(entity, "_attr_name"): + # The entity has a name + assert isinstance(entity._attr_name, str) and entity._attr_name + else: + # The only exception (for now) is IASZone + assert entity is IASZone diff --git a/tests/components/zha/zha_devices_list.py b/tests/components/zha/zha_devices_list.py index bc2de4f852c..0ec1ae8aa14 100644 --- a/tests/components/zha/zha_devices_list.py +++ b/tests/components/zha/zha_devices_list.py @@ -10,6 +10,16 @@ from zigpy.const import ( SIG_MODEL, SIG_NODE_DESC, ) +from zigpy.profiles import zha +from zigpy.zcl.clusters.closures import DoorLock +from zigpy.zcl.clusters.general import ( + Basic, + Groups, + Identify, + MultistateInput, + Ota, + Scenes, +) DEV_SIG_CLUSTER_HANDLERS = "cluster_handlers" DEV_SIG_DEV_NO = "device_no" @@ -19,6 +29,13 @@ DEV_SIG_ENT_MAP_ID = "entity_id" DEV_SIG_EP_ID = "endpoint_id" DEV_SIG_EVT_CLUSTER_HANDLERS = "event_cluster_handlers" DEV_SIG_ZHA_QUIRK = "zha_quirk" +DEV_SIG_ATTRIBUTES = "attributes" + + +PROFILE_ID = SIG_EP_PROFILE +DEVICE_TYPE = SIG_EP_TYPE +INPUT_CLUSTERS = SIG_EP_INPUT +OUTPUT_CLUSTERS = SIG_EP_OUTPUT DEVICES = [ { @@ -1629,7 +1646,7 @@ DEVICES = [ ("cover", "00:11:22:33:44:55:66:77-1"): { DEV_SIG_CLUSTER_HANDLERS: ["level", "on_off"], DEV_SIG_ENT_MAP_CLASS: "KeenVent", - DEV_SIG_ENT_MAP_ID: "cover.keen_home_inc_sv02_610_mp_1_3_keenvent", + DEV_SIG_ENT_MAP_ID: "cover.keen_home_inc_sv02_610_mp_1_3_keen_vent", }, ("sensor", "00:11:22:33:44:55:66:77-1-1"): { DEV_SIG_CLUSTER_HANDLERS: ["power"], @@ -1682,7 +1699,7 @@ DEVICES = [ ("cover", "00:11:22:33:44:55:66:77-1"): { DEV_SIG_CLUSTER_HANDLERS: ["level", "on_off"], DEV_SIG_ENT_MAP_CLASS: "KeenVent", - DEV_SIG_ENT_MAP_ID: "cover.keen_home_inc_sv02_612_mp_1_2_keenvent", + DEV_SIG_ENT_MAP_ID: "cover.keen_home_inc_sv02_612_mp_1_2_keen_vent", }, ("sensor", "00:11:22:33:44:55:66:77-1-1"): { DEV_SIG_CLUSTER_HANDLERS: ["power"], @@ -1735,7 +1752,7 @@ DEVICES = [ ("cover", "00:11:22:33:44:55:66:77-1"): { DEV_SIG_CLUSTER_HANDLERS: ["level", "on_off"], DEV_SIG_ENT_MAP_CLASS: "KeenVent", - DEV_SIG_ENT_MAP_ID: "cover.keen_home_inc_sv02_612_mp_1_3_keenvent", + DEV_SIG_ENT_MAP_ID: "cover.keen_home_inc_sv02_612_mp_1_3_keen_vent", }, ("sensor", "00:11:22:33:44:55:66:77-1-1"): { DEV_SIG_CLUSTER_HANDLERS: ["power"], @@ -2079,7 +2096,7 @@ DEVICES = [ ("binary_sensor", "00:11:22:33:44:55:66:77-100-15"): { DEV_SIG_CLUSTER_HANDLERS: ["binary_input"], DEV_SIG_ENT_MAP_CLASS: "BinaryInput", - DEV_SIG_ENT_MAP_ID: "binary_sensor.lumi_lumi_plug_maus01_binaryinput", + DEV_SIG_ENT_MAP_ID: "binary_sensor.lumi_lumi_plug_maus01_binary_input", }, ("sensor", "00:11:22:33:44:55:66:77-1-1794-summation_delivered"): { DEV_SIG_CLUSTER_HANDLERS: ["smartenergy_metering"], @@ -2969,7 +2986,7 @@ DEVICES = [ ("binary_sensor", "00:11:22:33:44:55:66:77-1-1280"): { DEV_SIG_CLUSTER_HANDLERS: ["ias_zone"], DEV_SIG_ENT_MAP_CLASS: "IASZone", - DEV_SIG_ENT_MAP_ID: "binary_sensor.lumi_lumi_sensor_motion_aq2_iaszone", + DEV_SIG_ENT_MAP_ID: "binary_sensor.lumi_lumi_sensor_motion_aq2_motion", }, ("button", "00:11:22:33:44:55:66:77-1-3"): { DEV_SIG_CLUSTER_HANDLERS: ["identify"], @@ -3029,7 +3046,7 @@ DEVICES = [ ("binary_sensor", "00:11:22:33:44:55:66:77-1-1280"): { DEV_SIG_CLUSTER_HANDLERS: ["ias_zone"], DEV_SIG_ENT_MAP_CLASS: "IASZone", - DEV_SIG_ENT_MAP_ID: "binary_sensor.lumi_lumi_sensor_smoke_iaszone", + DEV_SIG_ENT_MAP_ID: "binary_sensor.lumi_lumi_sensor_smoke_smoke", }, ("button", "00:11:22:33:44:55:66:77-1-3"): { DEV_SIG_CLUSTER_HANDLERS: ["identify"], @@ -3221,18 +3238,33 @@ DEVICES = [ SIG_NODE_DESC: b"\x02@\x807\x10\x7fd\x00\x00\x00d\x00\x00", SIG_ENDPOINTS: { 1: { - SIG_EP_TYPE: 10, - DEV_SIG_EP_ID: 1, - SIG_EP_INPUT: [0, 1, 3, 25, 257, 1280], - SIG_EP_OUTPUT: [0, 3, 4, 5, 25], - SIG_EP_PROFILE: 260, + PROFILE_ID: zha.PROFILE_ID, + DEVICE_TYPE: zha.DeviceType.DOOR_LOCK, + INPUT_CLUSTERS: [ + Basic.cluster_id, + Identify.cluster_id, + Ota.cluster_id, + DoorLock.cluster_id, + ], + OUTPUT_CLUSTERS: [ + Basic.cluster_id, + Identify.cluster_id, + Groups.cluster_id, + Scenes.cluster_id, + Ota.cluster_id, + DoorLock.cluster_id, + ], }, 2: { - SIG_EP_TYPE: 24322, - DEV_SIG_EP_ID: 2, - SIG_EP_INPUT: [3], - SIG_EP_OUTPUT: [3, 4, 5, 18], - SIG_EP_PROFILE: 260, + PROFILE_ID: zha.PROFILE_ID, + DEVICE_TYPE: 0x5F02, + INPUT_CLUSTERS: [Identify.cluster_id, MultistateInput.cluster_id], + OUTPUT_CLUSTERS: [ + Identify.cluster_id, + Groups.cluster_id, + Scenes.cluster_id, + MultistateInput.cluster_id, + ], }, }, DEV_SIG_EVT_CLUSTER_HANDLERS: ["1:0x0005", "1:0x0019", "2:0x0005"], @@ -3240,7 +3272,7 @@ DEVICES = [ ("binary_sensor", "00:11:22:33:44:55:66:77-1-1280"): { DEV_SIG_CLUSTER_HANDLERS: ["ias_zone"], DEV_SIG_ENT_MAP_CLASS: "IASZone", - DEV_SIG_ENT_MAP_ID: "binary_sensor.lumi_lumi_vibration_aq1_iaszone", + DEV_SIG_ENT_MAP_ID: "binary_sensor.lumi_lumi_vibration_aq1_vibration", }, ("button", "00:11:22:33:44:55:66:77-1-3"): { DEV_SIG_CLUSTER_HANDLERS: ["identify"], @@ -3262,10 +3294,10 @@ DEVICES = [ DEV_SIG_ENT_MAP_CLASS: "LQISensor", DEV_SIG_ENT_MAP_ID: "sensor.lumi_lumi_vibration_aq1_lqi", }, - ("lock", "00:11:22:33:44:55:66:77-1-257"): { - DEV_SIG_CLUSTER_HANDLERS: ["door_lock"], - DEV_SIG_ENT_MAP_CLASS: "ZhaDoorLock", - DEV_SIG_ENT_MAP_ID: "lock.lumi_lumi_vibration_aq1_doorlock", + ("sensor", "00:11:22:33:44:55:66:77-1-2"): { + DEV_SIG_CLUSTER_HANDLERS: ["device_temperature"], + DEV_SIG_ENT_MAP_CLASS: "DeviceTemperature", + DEV_SIG_ENT_MAP_ID: "sensor.lumi_lumi_vibration_aq1_device_temperature", }, }, }, @@ -3811,7 +3843,7 @@ DEVICES = [ ("binary_sensor", "00:11:22:33:44:55:66:77-2-15"): { DEV_SIG_CLUSTER_HANDLERS: ["binary_input"], DEV_SIG_ENT_MAP_CLASS: "BinaryInput", - DEV_SIG_ENT_MAP_ID: "binary_sensor.philips_rwl020_binaryinput", + DEV_SIG_ENT_MAP_ID: "binary_sensor.philips_rwl020_binary_input", }, ("button", "00:11:22:33:44:55:66:77-2-3"): { DEV_SIG_CLUSTER_HANDLERS: ["identify"], @@ -4332,7 +4364,7 @@ DEVICES = [ "sinope_manufacturer_specific", ], DEV_SIG_ENT_MAP_CLASS: "SinopeTechnologiesThermostat", - DEV_SIG_ENT_MAP_ID: "climate.sinope_technologies_th1123zb_sinopetechnologiesthermostat", + DEV_SIG_ENT_MAP_ID: "climate.sinope_technologies_th1123zb_thermostat", }, ("sensor", "00:11:22:33:44:55:66:77-1-2820"): { DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"], @@ -4422,7 +4454,7 @@ DEVICES = [ "sinope_manufacturer_specific", ], DEV_SIG_ENT_MAP_CLASS: "SinopeTechnologiesThermostat", - DEV_SIG_ENT_MAP_ID: "climate.sinope_technologies_th1124zb_sinopetechnologiesthermostat", + DEV_SIG_ENT_MAP_ID: "climate.sinope_technologies_th1124zb_thermostat", }, ("sensor", "00:11:22:33:44:55:66:77-1-2820"): { DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"], @@ -4497,7 +4529,7 @@ DEVICES = [ ("binary_sensor", "00:11:22:33:44:55:66:77-1-15"): { DEV_SIG_CLUSTER_HANDLERS: ["binary_input"], DEV_SIG_ENT_MAP_CLASS: "BinaryInput", - DEV_SIG_ENT_MAP_ID: "binary_sensor.smartthings_outletv4_binaryinput", + DEV_SIG_ENT_MAP_ID: "binary_sensor.smartthings_outletv4_binary_input", }, ("button", "00:11:22:33:44:55:66:77-1-3"): { DEV_SIG_CLUSTER_HANDLERS: ["identify"], @@ -4570,12 +4602,12 @@ DEVICES = [ ("device_tracker", "00:11:22:33:44:55:66:77-1"): { DEV_SIG_CLUSTER_HANDLERS: ["power"], DEV_SIG_ENT_MAP_CLASS: "ZHADeviceScannerEntity", - DEV_SIG_ENT_MAP_ID: "device_tracker.smartthings_tagv4_devicescanner", + DEV_SIG_ENT_MAP_ID: "device_tracker.smartthings_tagv4_device_scanner", }, ("binary_sensor", "00:11:22:33:44:55:66:77-1-15"): { DEV_SIG_CLUSTER_HANDLERS: ["binary_input"], DEV_SIG_ENT_MAP_CLASS: "BinaryInput", - DEV_SIG_ENT_MAP_ID: "binary_sensor.smartthings_tagv4_binaryinput", + DEV_SIG_ENT_MAP_ID: "binary_sensor.smartthings_tagv4_binary_input", }, ("button", "00:11:22:33:44:55:66:77-1-3"): { DEV_SIG_CLUSTER_HANDLERS: ["identify"], @@ -4747,7 +4779,7 @@ DEVICES = [ ("climate", "00:11:22:33:44:55:66:77-1"): { DEV_SIG_CLUSTER_HANDLERS: ["thermostat", "fan"], DEV_SIG_ENT_MAP_CLASS: "ZenWithinThermostat", - DEV_SIG_ENT_MAP_ID: "climate.zen_within_zen_01_zenwithinthermostat", + DEV_SIG_ENT_MAP_ID: "climate.zen_within_zen_01_thermostat", }, ("sensor", "00:11:22:33:44:55:66:77-1-1"): { DEV_SIG_CLUSTER_HANDLERS: ["power"], @@ -4902,7 +4934,7 @@ DEVICES = [ ("light", "00:11:22:33:44:55:66:77-1"): { DEV_SIG_CLUSTER_HANDLERS: ["on_off", "level"], DEV_SIG_ENT_MAP_CLASS: "MinTransitionLight", - DEV_SIG_ENT_MAP_ID: "light.sengled_e11_g13_mintransitionlight", + DEV_SIG_ENT_MAP_ID: "light.sengled_e11_g13_light", }, ("button", "00:11:22:33:44:55:66:77-1-3"): { DEV_SIG_CLUSTER_HANDLERS: ["identify"], @@ -4950,7 +4982,7 @@ DEVICES = [ ("light", "00:11:22:33:44:55:66:77-1"): { DEV_SIG_CLUSTER_HANDLERS: ["on_off", "level"], DEV_SIG_ENT_MAP_CLASS: "MinTransitionLight", - DEV_SIG_ENT_MAP_ID: "light.sengled_e12_n14_mintransitionlight", + DEV_SIG_ENT_MAP_ID: "light.sengled_e12_n14_light", }, ("button", "00:11:22:33:44:55:66:77-1-3"): { DEV_SIG_CLUSTER_HANDLERS: ["identify"], @@ -4998,7 +5030,7 @@ DEVICES = [ ("light", "00:11:22:33:44:55:66:77-1"): { DEV_SIG_CLUSTER_HANDLERS: ["on_off", "level", "light_color"], DEV_SIG_ENT_MAP_CLASS: "MinTransitionLight", - DEV_SIG_ENT_MAP_ID: "light.sengled_z01_a19nae26_mintransitionlight", + DEV_SIG_ENT_MAP_ID: "light.sengled_z01_a19nae26_light", }, ("button", "00:11:22:33:44:55:66:77-1-3"): { DEV_SIG_CLUSTER_HANDLERS: ["identify"], @@ -5189,7 +5221,7 @@ DEVICES = [ ("sensor", "00:11:22:33:44:55:66:77-208-12"): { DEV_SIG_CLUSTER_HANDLERS: ["analog_input"], DEV_SIG_ENT_MAP_CLASS: "AnalogInput", - DEV_SIG_ENT_MAP_ID: "sensor.digi_xbee3_analoginput", + DEV_SIG_ENT_MAP_ID: "sensor.digi_xbee3_analog_input", }, ("switch", "00:11:22:33:44:55:66:77-208-6"): { DEV_SIG_CLUSTER_HANDLERS: ["on_off"], @@ -5199,7 +5231,7 @@ DEVICES = [ ("sensor", "00:11:22:33:44:55:66:77-209-12"): { DEV_SIG_CLUSTER_HANDLERS: ["analog_input"], DEV_SIG_ENT_MAP_CLASS: "AnalogInput", - DEV_SIG_ENT_MAP_ID: "sensor.digi_xbee3_analoginput_2", + DEV_SIG_ENT_MAP_ID: "sensor.digi_xbee3_analog_input_2", }, ("switch", "00:11:22:33:44:55:66:77-209-6"): { DEV_SIG_CLUSTER_HANDLERS: ["on_off"], @@ -5209,7 +5241,7 @@ DEVICES = [ ("sensor", "00:11:22:33:44:55:66:77-210-12"): { DEV_SIG_CLUSTER_HANDLERS: ["analog_input"], DEV_SIG_ENT_MAP_CLASS: "AnalogInput", - DEV_SIG_ENT_MAP_ID: "sensor.digi_xbee3_analoginput_3", + DEV_SIG_ENT_MAP_ID: "sensor.digi_xbee3_analog_input_3", }, ("switch", "00:11:22:33:44:55:66:77-210-6"): { DEV_SIG_CLUSTER_HANDLERS: ["on_off"], @@ -5219,7 +5251,7 @@ DEVICES = [ ("sensor", "00:11:22:33:44:55:66:77-211-12"): { DEV_SIG_CLUSTER_HANDLERS: ["analog_input"], DEV_SIG_ENT_MAP_CLASS: "AnalogInput", - DEV_SIG_ENT_MAP_ID: "sensor.digi_xbee3_analoginput_4", + DEV_SIG_ENT_MAP_ID: "sensor.digi_xbee3_analog_input_4", }, ("switch", "00:11:22:33:44:55:66:77-211-6"): { DEV_SIG_CLUSTER_HANDLERS: ["on_off"], @@ -5244,7 +5276,7 @@ DEVICES = [ ("sensor", "00:11:22:33:44:55:66:77-215-12"): { DEV_SIG_CLUSTER_HANDLERS: ["analog_input"], DEV_SIG_ENT_MAP_CLASS: "AnalogInput", - DEV_SIG_ENT_MAP_ID: "sensor.digi_xbee3_analoginput_5", + DEV_SIG_ENT_MAP_ID: "sensor.digi_xbee3_analog_input_5", }, ("switch", "00:11:22:33:44:55:66:77-215-6"): { DEV_SIG_CLUSTER_HANDLERS: ["on_off"],