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):
"""Entity for ZHA alarm control devices."""
_attr_name: str = "Alarm control panel"
_attr_code_format = CodeFormat.TEXT
_attr_supported_features = (
AlarmControlPanelEntityFeature.ARM_HOME

View File

@ -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"})

View File

@ -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."""

View File

@ -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:

View File

@ -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."""

View File

@ -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."""

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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:

View File

@ -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)

View File

@ -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,

View File

@ -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(

View File

@ -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)

View File

@ -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(

View File

@ -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,
)

View File

@ -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

View File

@ -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"],