Clean up default ZHA entity names (#91841)

* Always use `Light` for lights, including subclasses

* Clean up other platforms

* Add a unit test to ensure all future entity classes have names

* Remove stale `_name`

* Address review feedback and rename `Open` to `Opening`
This commit is contained in:
puddly 2023-04-25 19:51:39 -04:00 committed by GitHub
parent da05763a5c
commit 6842cdcb65
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 180 additions and 79 deletions

View File

@ -81,6 +81,7 @@ async def async_setup_entry(
class ZHAAlarmControlPanel(ZhaEntity, AlarmControlPanelEntity): class ZHAAlarmControlPanel(ZhaEntity, AlarmControlPanelEntity):
"""Entity for ZHA alarm control devices.""" """Entity for ZHA alarm control devices."""
_attr_name: str = "Alarm control panel"
_attr_code_format = CodeFormat.TEXT _attr_code_format = CodeFormat.TEXT
_attr_supported_features = ( _attr_supported_features = (
AlarmControlPanelEntityFeature.ARM_HOME AlarmControlPanelEntityFeature.ARM_HOME

View File

@ -33,13 +33,22 @@ from .core.registries import ZHA_ENTITIES
from .entity import ZhaEntity from .entity import ZhaEntity
# Zigbee Cluster Library Zone Type to Home Assistant device class # Zigbee Cluster Library Zone Type to Home Assistant device class
CLASS_MAPPING = { IAS_ZONE_CLASS_MAPPING = {
0x000D: BinarySensorDeviceClass.MOTION, IasZone.ZoneType.Motion_Sensor: BinarySensorDeviceClass.MOTION,
0x0015: BinarySensorDeviceClass.OPENING, IasZone.ZoneType.Contact_Switch: BinarySensorDeviceClass.OPENING,
0x0028: BinarySensorDeviceClass.SMOKE, IasZone.ZoneType.Fire_Sensor: BinarySensorDeviceClass.SMOKE,
0x002A: BinarySensorDeviceClass.MOISTURE, IasZone.ZoneType.Water_Sensor: BinarySensorDeviceClass.MOISTURE,
0x002B: BinarySensorDeviceClass.GAS, IasZone.ZoneType.Carbon_Monoxide_Sensor: BinarySensorDeviceClass.GAS,
0x002D: BinarySensorDeviceClass.VIBRATION, 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) STRICT_MATCH = functools.partial(ZHA_ENTITIES.strict_match, Platform.BINARY_SENSOR)
@ -108,6 +117,7 @@ class Accelerometer(BinarySensor):
"""ZHA BinarySensor.""" """ZHA BinarySensor."""
SENSOR_ATTR = "acceleration" SENSOR_ATTR = "acceleration"
_attr_name: str = "Accelerometer"
_attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.MOVING _attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.MOVING
@ -116,6 +126,7 @@ class Occupancy(BinarySensor):
"""ZHA BinarySensor.""" """ZHA BinarySensor."""
SENSOR_ATTR = "occupancy" SENSOR_ATTR = "occupancy"
_attr_name: str = "Occupancy"
_attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.OCCUPANCY _attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.OCCUPANCY
@ -124,6 +135,7 @@ class Opening(BinarySensor):
"""ZHA OnOff BinarySensor.""" """ZHA OnOff BinarySensor."""
SENSOR_ATTR = "on_off" SENSOR_ATTR = "on_off"
_attr_name: str = "Opening"
_attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.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. # 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.""" """ZHA BinarySensor."""
SENSOR_ATTR = "present_value" SENSOR_ATTR = "present_value"
_attr_name: str = "Binary input"
@STRICT_MATCH( @STRICT_MATCH(
@ -159,6 +172,7 @@ class BinaryInput(BinarySensor):
class Motion(Opening): class Motion(Opening):
"""ZHA OnOff BinarySensor with motion device class.""" """ZHA OnOff BinarySensor with motion device class."""
_attr_name: str = "Motion"
_attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.MOTION _attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.MOTION
@ -168,10 +182,17 @@ class IASZone(BinarySensor):
SENSOR_ATTR = "zone_status" 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 @property
def device_class(self) -> BinarySensorDeviceClass | None: def device_class(self) -> BinarySensorDeviceClass | None:
"""Return device class from component DEVICE_CLASSES.""" """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 @staticmethod
def parse(value: bool | int) -> bool: def parse(value: bool | int) -> bool:
@ -220,6 +241,7 @@ class FrostLock(BinarySensor, id_suffix="frost_lock"):
SENSOR_ATTR = "frost_lock" SENSOR_ATTR = "frost_lock"
_attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.LOCK _attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.LOCK
_attr_name: str = "Frost lock"
@MULTI_MATCH(cluster_handler_names="ikea_airpurifier") @MULTI_MATCH(cluster_handler_names="ikea_airpurifier")
@ -228,6 +250,7 @@ class ReplaceFilter(BinarySensor, id_suffix="replace_filter"):
SENSOR_ATTR = "replace_filter" SENSOR_ATTR = "replace_filter"
_attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.PROBLEM _attr_device_class: BinarySensorDeviceClass = BinarySensorDeviceClass.PROBLEM
_attr_name: str = "Replace filter"
@MULTI_MATCH(cluster_handler_names="opple_cluster", models={"aqara.feeder.acn001"}) @MULTI_MATCH(cluster_handler_names="opple_cluster", models={"aqara.feeder.acn001"})

View File

@ -139,6 +139,7 @@ class Thermostat(ZhaEntity, ClimateEntity):
_attr_precision = PRECISION_TENTHS _attr_precision = PRECISION_TENTHS
_attr_temperature_unit = UnitOfTemperature.CELSIUS _attr_temperature_unit = UnitOfTemperature.CELSIUS
_attr_name: str = "Thermostat"
def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs): def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs):
"""Initialize ZHA Thermostat instance.""" """Initialize ZHA Thermostat instance."""

View File

@ -71,6 +71,8 @@ async def async_setup_entry(
class ZhaCover(ZhaEntity, CoverEntity): class ZhaCover(ZhaEntity, CoverEntity):
"""Representation of a ZHA cover.""" """Representation of a ZHA cover."""
_attr_name: str = "Cover"
def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs): def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs):
"""Init this sensor.""" """Init this sensor."""
super().__init__(unique_id, zha_device, cluster_handlers, **kwargs) super().__init__(unique_id, zha_device, cluster_handlers, **kwargs)
@ -197,6 +199,7 @@ class Shade(ZhaEntity, CoverEntity):
"""ZHA Shade.""" """ZHA Shade."""
_attr_device_class = CoverDeviceClass.SHADE _attr_device_class = CoverDeviceClass.SHADE
_attr_name: str = "Shade"
def __init__( def __init__(
self, self,
@ -308,6 +311,8 @@ class Shade(ZhaEntity, CoverEntity):
class KeenVent(Shade): class KeenVent(Shade):
"""Keen vent cover.""" """Keen vent cover."""
_attr_name: str = "Keen vent"
_attr_device_class = CoverDeviceClass.DAMPER _attr_device_class = CoverDeviceClass.DAMPER
async def async_open_cover(self, **kwargs: Any) -> None: async def async_open_cover(self, **kwargs: Any) -> None:

View File

@ -49,6 +49,7 @@ class ZHADeviceScannerEntity(ScannerEntity, ZhaEntity):
"""Represent a tracked device.""" """Represent a tracked device."""
_attr_should_poll = True # BaseZhaEntity defaults to False _attr_should_poll = True # BaseZhaEntity defaults to False
_attr_name: str = "Device scanner"
def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs): def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs):
"""Initialize the ZHA device tracker.""" """Initialize the ZHA device tracker."""

View File

@ -52,7 +52,6 @@ class BaseZhaEntity(LogMixin, entity.Entity):
def __init__(self, unique_id: str, zha_device: ZHADevice, **kwargs: Any) -> None: def __init__(self, unique_id: str, zha_device: ZHADevice, **kwargs: Any) -> None:
"""Init ZHA entity.""" """Init ZHA entity."""
self._name: str = ""
self._unique_id: str = unique_id self._unique_id: str = unique_id
if self.unique_id_suffix: if self.unique_id_suffix:
self._unique_id += f"-{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._unsubs: list[Callable[[], None]] = []
self.remove_future: asyncio.Future[Any] = asyncio.Future() 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 @property
def unique_id(self) -> str: def unique_id(self) -> str:
"""Return a unique ID.""" """Return a unique ID."""
@ -167,13 +159,7 @@ class ZhaEntity(BaseZhaEntity, RestoreEntity):
) -> None: ) -> None:
"""Init ZHA entity.""" """Init ZHA entity."""
super().__init__(unique_id, zha_device, **kwargs) 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] = {} self.cluster_handlers: dict[str, ClusterHandler] = {}
for cluster_handler in cluster_handlers: for cluster_handler in cluster_handlers:
self.cluster_handlers[cluster_handler.name] = cluster_handler self.cluster_handlers[cluster_handler.name] = cluster_handler
@ -249,6 +235,9 @@ class ZhaEntity(BaseZhaEntity, RestoreEntity):
class ZhaGroupEntity(BaseZhaEntity): class ZhaGroupEntity(BaseZhaEntity):
"""A base class for ZHA group entities.""" """A base class for ZHA group entities."""
# The group name is set in the initializer
_attr_name: str
def __init__( def __init__(
self, self,
entity_ids: list[str], entity_ids: list[str],
@ -261,9 +250,6 @@ class ZhaGroupEntity(BaseZhaEntity):
super().__init__(unique_id, zha_device, **kwargs) super().__init__(unique_id, zha_device, **kwargs)
self._available = False self._available = False
self._group = zha_device.gateway.groups.get(group_id) 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._group_id: int = group_id
self._entity_ids: list[str] = entity_ids self._entity_ids: list[str] = entity_ids
self._async_unsub_state_changed: CALLBACK_TYPE | None = None self._async_unsub_state_changed: CALLBACK_TYPE | None = None
@ -271,6 +257,8 @@ class ZhaGroupEntity(BaseZhaEntity):
self._change_listener_debouncer: Debouncer | None = None self._change_listener_debouncer: Debouncer | None = None
self._update_group_from_child_delay = DEFAULT_UPDATE_GROUP_FROM_CHILD_DELAY self._update_group_from_child_delay = DEFAULT_UPDATE_GROUP_FROM_CHILD_DELAY
self._attr_name = self._group.name
@property @property
def available(self) -> bool: def available(self) -> bool:
"""Return entity availability.""" """Return entity availability."""

View File

@ -136,6 +136,8 @@ class BaseFan(FanEntity):
class ZhaFan(BaseFan, ZhaEntity): class ZhaFan(BaseFan, ZhaEntity):
"""Representation of a ZHA fan.""" """Representation of a ZHA fan."""
_attr_name: str = "Fan"
def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs): def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs):
"""Init this sensor.""" """Init this sensor."""
super().__init__(unique_id, zha_device, cluster_handlers, **kwargs) 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): class IkeaFan(BaseFan, ZhaEntity):
"""Representation of a ZHA fan.""" """Representation of a ZHA fan."""
_attr_name: str = "IKEA fan"
def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs): def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs):
"""Init this sensor.""" """Init this sensor."""
super().__init__(unique_id, zha_device, cluster_handlers, **kwargs) super().__init__(unique_id, zha_device, cluster_handlers, **kwargs)

View File

@ -637,6 +637,7 @@ class BaseLight(LogMixin, light.LightEntity):
class Light(BaseLight, ZhaEntity): class Light(BaseLight, ZhaEntity):
"""Representation of a ZHA or ZLL light.""" """Representation of a ZHA or ZLL light."""
_attr_name: str = "Light"
_attr_supported_color_modes: set[ColorMode] _attr_supported_color_modes: set[ColorMode]
_REFRESH_INTERVAL = (45, 75) _REFRESH_INTERVAL = (45, 75)
@ -1065,6 +1066,7 @@ class Light(BaseLight, ZhaEntity):
class HueLight(Light): class HueLight(Light):
"""Representation of a HUE light which does not report attributes.""" """Representation of a HUE light which does not report attributes."""
_attr_name: str = "Light"
_REFRESH_INTERVAL = (3, 5) _REFRESH_INTERVAL = (3, 5)
@ -1076,6 +1078,7 @@ class HueLight(Light):
class ForceOnLight(Light): class ForceOnLight(Light):
"""Representation of a light which does not respect move_to_level_with_on_off.""" """Representation of a light which does not respect move_to_level_with_on_off."""
_attr_name: str = "Light"
_FORCE_ON = True _FORCE_ON = True
@ -1087,6 +1090,7 @@ class ForceOnLight(Light):
class MinTransitionLight(Light): class MinTransitionLight(Light):
"""Representation of a light which does not react to any "move to" calls with 0 as a transition.""" """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 _DEFAULT_MIN_TRANSITION_TIME = 1

View File

@ -96,6 +96,8 @@ async def async_setup_entry(
class ZhaDoorLock(ZhaEntity, LockEntity): class ZhaDoorLock(ZhaEntity, LockEntity):
"""Representation of a ZHA lock.""" """Representation of a ZHA lock."""
_attr_name: str = "Door lock"
def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs): def __init__(self, unique_id, zha_device, cluster_handlers, **kwargs):
"""Init this sensor.""" """Init this sensor."""
super().__init__(unique_id, zha_device, cluster_handlers, **kwargs) super().__init__(unique_id, zha_device, cluster_handlers, **kwargs)

View File

@ -279,6 +279,8 @@ async def async_setup_entry(
class ZhaNumber(ZhaEntity, NumberEntity): class ZhaNumber(ZhaEntity, NumberEntity):
"""Representation of a ZHA Number entity.""" """Representation of a ZHA Number entity."""
_attr_name: str = "Number"
def __init__( def __init__(
self, self,
unique_id: str, unique_id: str,
@ -331,7 +333,7 @@ class ZhaNumber(ZhaEntity, NumberEntity):
return super().native_step return super().native_step
@property @property
def name(self) -> str: def name(self) -> str | None:
"""Return the name of the number entity.""" """Return the name of the number entity."""
description = self._analog_output_cluster_handler.description description = self._analog_output_cluster_handler.description
if description is not None and len(description) > 0: if description is not None and len(description) > 0:

View File

@ -191,6 +191,7 @@ class AnalogInput(Sensor):
"""Sensor that displays analog input values.""" """Sensor that displays analog input values."""
SENSOR_ATTR = "present_value" SENSOR_ATTR = "present_value"
_attr_name: str = "Analog input"
@MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_POWER_CONFIGURATION) @MULTI_MATCH(cluster_handler_names=CLUSTER_HANDLER_POWER_CONFIGURATION)

View File

@ -74,6 +74,8 @@ async def async_setup_entry(
class ZHASiren(ZhaEntity, SirenEntity): class ZHASiren(ZhaEntity, SirenEntity):
"""Representation of a ZHA siren.""" """Representation of a ZHA siren."""
_attr_name: str = "Siren"
def __init__( def __init__(
self, self,
unique_id: str, unique_id: str,

View File

@ -64,6 +64,8 @@ async def async_setup_entry(
class Switch(ZhaEntity, SwitchEntity): class Switch(ZhaEntity, SwitchEntity):
"""ZHA switch.""" """ZHA switch."""
_attr_name: str = "Switch"
def __init__( def __init__(
self, self,
unique_id: str, unique_id: str,
@ -286,6 +288,7 @@ class OnOffWindowDetectionFunctionConfigurationEntity(
_zcl_attribute: str = "window_detection_function" _zcl_attribute: str = "window_detection_function"
_zcl_inverter_attribute: str = "window_detection_function_inverter" _zcl_inverter_attribute: str = "window_detection_function_inverter"
_attr_name: str = "Invert window detection"
@CONFIG_DIAGNOSTIC_MATCH( @CONFIG_DIAGNOSTIC_MATCH(

View File

@ -167,7 +167,9 @@ def find_entity_ids(domain, zha_device, hass):
def async_find_group_entity_id(hass, domain, group): def async_find_group_entity_id(hass, domain, group):
"""Find the group entity id under test.""" """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) entity_ids = hass.states.async_entity_ids(domain)

View File

@ -199,6 +199,7 @@ def zigpy_device_mock(zigpy_app_controller):
nwk=0xB79C, nwk=0xB79C,
patch_cluster=True, patch_cluster=True,
quirk=None, quirk=None,
attributes=None,
): ):
"""Make a fake device using the specified cluster classes.""" """Make a fake device using the specified cluster classes."""
device = zigpy.device.Device( device = zigpy.device.Device(

View File

@ -36,6 +36,7 @@ import homeassistant.helpers.entity_registry as er
from .common import get_zha_gateway from .common import get_zha_gateway
from .conftest import SIG_EP_INPUT, SIG_EP_OUTPUT, SIG_EP_PROFILE, SIG_EP_TYPE from .conftest import SIG_EP_INPUT, SIG_EP_OUTPUT, SIG_EP_PROFILE, SIG_EP_TYPE
from .zha_devices_list import ( from .zha_devices_list import (
DEV_SIG_ATTRIBUTES,
DEV_SIG_CLUSTER_HANDLERS, DEV_SIG_CLUSTER_HANDLERS,
DEV_SIG_ENT_MAP, DEV_SIG_ENT_MAP,
DEV_SIG_ENT_MAP_CLASS, DEV_SIG_ENT_MAP_CLASS,
@ -89,11 +90,12 @@ async def test_devices(
entity_registry = er.async_get(hass_disable_services) entity_registry = er.async_get(hass_disable_services)
zigpy_device = zigpy_device_mock( zigpy_device = zigpy_device_mock(
device[SIG_ENDPOINTS], endpoints=device[SIG_ENDPOINTS],
"00:11:22:33:44:55:66:77", ieee="00:11:22:33:44:55:66:77",
device[SIG_MANUFACTURER], manufacturer=device[SIG_MANUFACTURER],
device[SIG_MODEL], model=device[SIG_MODEL],
node_descriptor=device[SIG_NODE_DESC], node_descriptor=device[SIG_NODE_DESC],
attributes=device.get(DEV_SIG_ATTRIBUTES),
patch_cluster=False, patch_cluster=False,
) )

View File

@ -1,14 +1,21 @@
"""Test ZHA registries.""" """Test ZHA registries."""
from __future__ import annotations
import importlib import importlib
import inspect import inspect
import typing
from unittest import mock from unittest import mock
import pytest import pytest
import zhaquirks import zhaquirks
from homeassistant.components.zha.binary_sensor import IASZone
import homeassistant.components.zha.core.registries as registries import homeassistant.components.zha.core.registries as registries
from homeassistant.helpers import entity_registry as er from homeassistant.helpers import entity_registry as er
if typing.TYPE_CHECKING:
from homeassistant.components.zha.core.entity import ZhaEntity
MANUFACTURER = "mock manufacturer" MANUFACTURER = "mock manufacturer"
MODEL = "mock model" MODEL = "mock model"
QUIRK_CLASS = "mock.class" 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: def test_quirk_classes() -> None:
"""Make sure that quirk_classes in components matches are valid.""" """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]): if not find_quirk_class(zhaquirks, quirk_tok[0], quirk_tok[1]):
raise ValueError(f"Quirk class '{value}' does not exists.") raise ValueError(f"Quirk class '{value}' does not exists.")
for component in registries.ZHA_ENTITIES._strict_registry.items(): for rule, _ in iter_all_rules():
for rule in component[1].items(): quirk_class_validator(rule.quirk_classes)
quirk_class_validator(rule[0].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(): def test_entity_names() -> None:
for item in component[1].items(): """Make sure that all handlers expose entities with valid names."""
for rule in item[1].items():
quirk_class_validator(rule[0].quirk_classes) 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

View File

@ -10,6 +10,16 @@ from zigpy.const import (
SIG_MODEL, SIG_MODEL,
SIG_NODE_DESC, 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_CLUSTER_HANDLERS = "cluster_handlers"
DEV_SIG_DEV_NO = "device_no" 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_EP_ID = "endpoint_id"
DEV_SIG_EVT_CLUSTER_HANDLERS = "event_cluster_handlers" DEV_SIG_EVT_CLUSTER_HANDLERS = "event_cluster_handlers"
DEV_SIG_ZHA_QUIRK = "zha_quirk" 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 = [ DEVICES = [
{ {
@ -1629,7 +1646,7 @@ DEVICES = [
("cover", "00:11:22:33:44:55:66:77-1"): { ("cover", "00:11:22:33:44:55:66:77-1"): {
DEV_SIG_CLUSTER_HANDLERS: ["level", "on_off"], DEV_SIG_CLUSTER_HANDLERS: ["level", "on_off"],
DEV_SIG_ENT_MAP_CLASS: "KeenVent", 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"): { ("sensor", "00:11:22:33:44:55:66:77-1-1"): {
DEV_SIG_CLUSTER_HANDLERS: ["power"], DEV_SIG_CLUSTER_HANDLERS: ["power"],
@ -1682,7 +1699,7 @@ DEVICES = [
("cover", "00:11:22:33:44:55:66:77-1"): { ("cover", "00:11:22:33:44:55:66:77-1"): {
DEV_SIG_CLUSTER_HANDLERS: ["level", "on_off"], DEV_SIG_CLUSTER_HANDLERS: ["level", "on_off"],
DEV_SIG_ENT_MAP_CLASS: "KeenVent", 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"): { ("sensor", "00:11:22:33:44:55:66:77-1-1"): {
DEV_SIG_CLUSTER_HANDLERS: ["power"], DEV_SIG_CLUSTER_HANDLERS: ["power"],
@ -1735,7 +1752,7 @@ DEVICES = [
("cover", "00:11:22:33:44:55:66:77-1"): { ("cover", "00:11:22:33:44:55:66:77-1"): {
DEV_SIG_CLUSTER_HANDLERS: ["level", "on_off"], DEV_SIG_CLUSTER_HANDLERS: ["level", "on_off"],
DEV_SIG_ENT_MAP_CLASS: "KeenVent", 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"): { ("sensor", "00:11:22:33:44:55:66:77-1-1"): {
DEV_SIG_CLUSTER_HANDLERS: ["power"], DEV_SIG_CLUSTER_HANDLERS: ["power"],
@ -2079,7 +2096,7 @@ DEVICES = [
("binary_sensor", "00:11:22:33:44:55:66:77-100-15"): { ("binary_sensor", "00:11:22:33:44:55:66:77-100-15"): {
DEV_SIG_CLUSTER_HANDLERS: ["binary_input"], DEV_SIG_CLUSTER_HANDLERS: ["binary_input"],
DEV_SIG_ENT_MAP_CLASS: "BinaryInput", 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"): { ("sensor", "00:11:22:33:44:55:66:77-1-1794-summation_delivered"): {
DEV_SIG_CLUSTER_HANDLERS: ["smartenergy_metering"], DEV_SIG_CLUSTER_HANDLERS: ["smartenergy_metering"],
@ -2969,7 +2986,7 @@ DEVICES = [
("binary_sensor", "00:11:22:33:44:55:66:77-1-1280"): { ("binary_sensor", "00:11:22:33:44:55:66:77-1-1280"): {
DEV_SIG_CLUSTER_HANDLERS: ["ias_zone"], DEV_SIG_CLUSTER_HANDLERS: ["ias_zone"],
DEV_SIG_ENT_MAP_CLASS: "IASZone", 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"): { ("button", "00:11:22:33:44:55:66:77-1-3"): {
DEV_SIG_CLUSTER_HANDLERS: ["identify"], DEV_SIG_CLUSTER_HANDLERS: ["identify"],
@ -3029,7 +3046,7 @@ DEVICES = [
("binary_sensor", "00:11:22:33:44:55:66:77-1-1280"): { ("binary_sensor", "00:11:22:33:44:55:66:77-1-1280"): {
DEV_SIG_CLUSTER_HANDLERS: ["ias_zone"], DEV_SIG_CLUSTER_HANDLERS: ["ias_zone"],
DEV_SIG_ENT_MAP_CLASS: "IASZone", 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"): { ("button", "00:11:22:33:44:55:66:77-1-3"): {
DEV_SIG_CLUSTER_HANDLERS: ["identify"], DEV_SIG_CLUSTER_HANDLERS: ["identify"],
@ -3221,18 +3238,33 @@ DEVICES = [
SIG_NODE_DESC: b"\x02@\x807\x10\x7fd\x00\x00\x00d\x00\x00", SIG_NODE_DESC: b"\x02@\x807\x10\x7fd\x00\x00\x00d\x00\x00",
SIG_ENDPOINTS: { SIG_ENDPOINTS: {
1: { 1: {
SIG_EP_TYPE: 10, PROFILE_ID: zha.PROFILE_ID,
DEV_SIG_EP_ID: 1, DEVICE_TYPE: zha.DeviceType.DOOR_LOCK,
SIG_EP_INPUT: [0, 1, 3, 25, 257, 1280], INPUT_CLUSTERS: [
SIG_EP_OUTPUT: [0, 3, 4, 5, 25], Basic.cluster_id,
SIG_EP_PROFILE: 260, 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: { 2: {
SIG_EP_TYPE: 24322, PROFILE_ID: zha.PROFILE_ID,
DEV_SIG_EP_ID: 2, DEVICE_TYPE: 0x5F02,
SIG_EP_INPUT: [3], INPUT_CLUSTERS: [Identify.cluster_id, MultistateInput.cluster_id],
SIG_EP_OUTPUT: [3, 4, 5, 18], OUTPUT_CLUSTERS: [
SIG_EP_PROFILE: 260, Identify.cluster_id,
Groups.cluster_id,
Scenes.cluster_id,
MultistateInput.cluster_id,
],
}, },
}, },
DEV_SIG_EVT_CLUSTER_HANDLERS: ["1:0x0005", "1:0x0019", "2:0x0005"], 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"): { ("binary_sensor", "00:11:22:33:44:55:66:77-1-1280"): {
DEV_SIG_CLUSTER_HANDLERS: ["ias_zone"], DEV_SIG_CLUSTER_HANDLERS: ["ias_zone"],
DEV_SIG_ENT_MAP_CLASS: "IASZone", 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"): { ("button", "00:11:22:33:44:55:66:77-1-3"): {
DEV_SIG_CLUSTER_HANDLERS: ["identify"], DEV_SIG_CLUSTER_HANDLERS: ["identify"],
@ -3262,10 +3294,10 @@ DEVICES = [
DEV_SIG_ENT_MAP_CLASS: "LQISensor", DEV_SIG_ENT_MAP_CLASS: "LQISensor",
DEV_SIG_ENT_MAP_ID: "sensor.lumi_lumi_vibration_aq1_lqi", DEV_SIG_ENT_MAP_ID: "sensor.lumi_lumi_vibration_aq1_lqi",
}, },
("lock", "00:11:22:33:44:55:66:77-1-257"): { ("sensor", "00:11:22:33:44:55:66:77-1-2"): {
DEV_SIG_CLUSTER_HANDLERS: ["door_lock"], DEV_SIG_CLUSTER_HANDLERS: ["device_temperature"],
DEV_SIG_ENT_MAP_CLASS: "ZhaDoorLock", DEV_SIG_ENT_MAP_CLASS: "DeviceTemperature",
DEV_SIG_ENT_MAP_ID: "lock.lumi_lumi_vibration_aq1_doorlock", 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"): { ("binary_sensor", "00:11:22:33:44:55:66:77-2-15"): {
DEV_SIG_CLUSTER_HANDLERS: ["binary_input"], DEV_SIG_CLUSTER_HANDLERS: ["binary_input"],
DEV_SIG_ENT_MAP_CLASS: "BinaryInput", 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"): { ("button", "00:11:22:33:44:55:66:77-2-3"): {
DEV_SIG_CLUSTER_HANDLERS: ["identify"], DEV_SIG_CLUSTER_HANDLERS: ["identify"],
@ -4332,7 +4364,7 @@ DEVICES = [
"sinope_manufacturer_specific", "sinope_manufacturer_specific",
], ],
DEV_SIG_ENT_MAP_CLASS: "SinopeTechnologiesThermostat", 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"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820"): {
DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"], DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"],
@ -4422,7 +4454,7 @@ DEVICES = [
"sinope_manufacturer_specific", "sinope_manufacturer_specific",
], ],
DEV_SIG_ENT_MAP_CLASS: "SinopeTechnologiesThermostat", 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"): { ("sensor", "00:11:22:33:44:55:66:77-1-2820"): {
DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"], DEV_SIG_CLUSTER_HANDLERS: ["electrical_measurement"],
@ -4497,7 +4529,7 @@ DEVICES = [
("binary_sensor", "00:11:22:33:44:55:66:77-1-15"): { ("binary_sensor", "00:11:22:33:44:55:66:77-1-15"): {
DEV_SIG_CLUSTER_HANDLERS: ["binary_input"], DEV_SIG_CLUSTER_HANDLERS: ["binary_input"],
DEV_SIG_ENT_MAP_CLASS: "BinaryInput", 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"): { ("button", "00:11:22:33:44:55:66:77-1-3"): {
DEV_SIG_CLUSTER_HANDLERS: ["identify"], DEV_SIG_CLUSTER_HANDLERS: ["identify"],
@ -4570,12 +4602,12 @@ DEVICES = [
("device_tracker", "00:11:22:33:44:55:66:77-1"): { ("device_tracker", "00:11:22:33:44:55:66:77-1"): {
DEV_SIG_CLUSTER_HANDLERS: ["power"], DEV_SIG_CLUSTER_HANDLERS: ["power"],
DEV_SIG_ENT_MAP_CLASS: "ZHADeviceScannerEntity", 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"): { ("binary_sensor", "00:11:22:33:44:55:66:77-1-15"): {
DEV_SIG_CLUSTER_HANDLERS: ["binary_input"], DEV_SIG_CLUSTER_HANDLERS: ["binary_input"],
DEV_SIG_ENT_MAP_CLASS: "BinaryInput", 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"): { ("button", "00:11:22:33:44:55:66:77-1-3"): {
DEV_SIG_CLUSTER_HANDLERS: ["identify"], DEV_SIG_CLUSTER_HANDLERS: ["identify"],
@ -4747,7 +4779,7 @@ DEVICES = [
("climate", "00:11:22:33:44:55:66:77-1"): { ("climate", "00:11:22:33:44:55:66:77-1"): {
DEV_SIG_CLUSTER_HANDLERS: ["thermostat", "fan"], DEV_SIG_CLUSTER_HANDLERS: ["thermostat", "fan"],
DEV_SIG_ENT_MAP_CLASS: "ZenWithinThermostat", 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"): { ("sensor", "00:11:22:33:44:55:66:77-1-1"): {
DEV_SIG_CLUSTER_HANDLERS: ["power"], DEV_SIG_CLUSTER_HANDLERS: ["power"],
@ -4902,7 +4934,7 @@ DEVICES = [
("light", "00:11:22:33:44:55:66:77-1"): { ("light", "00:11:22:33:44:55:66:77-1"): {
DEV_SIG_CLUSTER_HANDLERS: ["on_off", "level"], DEV_SIG_CLUSTER_HANDLERS: ["on_off", "level"],
DEV_SIG_ENT_MAP_CLASS: "MinTransitionLight", 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"): { ("button", "00:11:22:33:44:55:66:77-1-3"): {
DEV_SIG_CLUSTER_HANDLERS: ["identify"], DEV_SIG_CLUSTER_HANDLERS: ["identify"],
@ -4950,7 +4982,7 @@ DEVICES = [
("light", "00:11:22:33:44:55:66:77-1"): { ("light", "00:11:22:33:44:55:66:77-1"): {
DEV_SIG_CLUSTER_HANDLERS: ["on_off", "level"], DEV_SIG_CLUSTER_HANDLERS: ["on_off", "level"],
DEV_SIG_ENT_MAP_CLASS: "MinTransitionLight", 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"): { ("button", "00:11:22:33:44:55:66:77-1-3"): {
DEV_SIG_CLUSTER_HANDLERS: ["identify"], DEV_SIG_CLUSTER_HANDLERS: ["identify"],
@ -4998,7 +5030,7 @@ DEVICES = [
("light", "00:11:22:33:44:55:66:77-1"): { ("light", "00:11:22:33:44:55:66:77-1"): {
DEV_SIG_CLUSTER_HANDLERS: ["on_off", "level", "light_color"], DEV_SIG_CLUSTER_HANDLERS: ["on_off", "level", "light_color"],
DEV_SIG_ENT_MAP_CLASS: "MinTransitionLight", 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"): { ("button", "00:11:22:33:44:55:66:77-1-3"): {
DEV_SIG_CLUSTER_HANDLERS: ["identify"], DEV_SIG_CLUSTER_HANDLERS: ["identify"],
@ -5189,7 +5221,7 @@ DEVICES = [
("sensor", "00:11:22:33:44:55:66:77-208-12"): { ("sensor", "00:11:22:33:44:55:66:77-208-12"): {
DEV_SIG_CLUSTER_HANDLERS: ["analog_input"], DEV_SIG_CLUSTER_HANDLERS: ["analog_input"],
DEV_SIG_ENT_MAP_CLASS: "AnalogInput", 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"): { ("switch", "00:11:22:33:44:55:66:77-208-6"): {
DEV_SIG_CLUSTER_HANDLERS: ["on_off"], DEV_SIG_CLUSTER_HANDLERS: ["on_off"],
@ -5199,7 +5231,7 @@ DEVICES = [
("sensor", "00:11:22:33:44:55:66:77-209-12"): { ("sensor", "00:11:22:33:44:55:66:77-209-12"): {
DEV_SIG_CLUSTER_HANDLERS: ["analog_input"], DEV_SIG_CLUSTER_HANDLERS: ["analog_input"],
DEV_SIG_ENT_MAP_CLASS: "AnalogInput", 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"): { ("switch", "00:11:22:33:44:55:66:77-209-6"): {
DEV_SIG_CLUSTER_HANDLERS: ["on_off"], DEV_SIG_CLUSTER_HANDLERS: ["on_off"],
@ -5209,7 +5241,7 @@ DEVICES = [
("sensor", "00:11:22:33:44:55:66:77-210-12"): { ("sensor", "00:11:22:33:44:55:66:77-210-12"): {
DEV_SIG_CLUSTER_HANDLERS: ["analog_input"], DEV_SIG_CLUSTER_HANDLERS: ["analog_input"],
DEV_SIG_ENT_MAP_CLASS: "AnalogInput", 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"): { ("switch", "00:11:22:33:44:55:66:77-210-6"): {
DEV_SIG_CLUSTER_HANDLERS: ["on_off"], DEV_SIG_CLUSTER_HANDLERS: ["on_off"],
@ -5219,7 +5251,7 @@ DEVICES = [
("sensor", "00:11:22:33:44:55:66:77-211-12"): { ("sensor", "00:11:22:33:44:55:66:77-211-12"): {
DEV_SIG_CLUSTER_HANDLERS: ["analog_input"], DEV_SIG_CLUSTER_HANDLERS: ["analog_input"],
DEV_SIG_ENT_MAP_CLASS: "AnalogInput", 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"): { ("switch", "00:11:22:33:44:55:66:77-211-6"): {
DEV_SIG_CLUSTER_HANDLERS: ["on_off"], DEV_SIG_CLUSTER_HANDLERS: ["on_off"],
@ -5244,7 +5276,7 @@ DEVICES = [
("sensor", "00:11:22:33:44:55:66:77-215-12"): { ("sensor", "00:11:22:33:44:55:66:77-215-12"): {
DEV_SIG_CLUSTER_HANDLERS: ["analog_input"], DEV_SIG_CLUSTER_HANDLERS: ["analog_input"],
DEV_SIG_ENT_MAP_CLASS: "AnalogInput", 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"): { ("switch", "00:11:22:33:44:55:66:77-215-6"): {
DEV_SIG_CLUSTER_HANDLERS: ["on_off"], DEV_SIG_CLUSTER_HANDLERS: ["on_off"],