From a3061bda60c9136859224d55cd194d61a0b0a37c Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Tue, 31 Dec 2019 11:09:58 -0500 Subject: [PATCH] Make the rest of ZHA platforms to use ZHA class registry (#30261) * Refactor ZHA component tests fixtures. * Add tests for ZHA device discovery. * Refactor ZHA registry MatchRule. Allow callables as a matching criteria. Allow sets for model & manufacturer. * Minor ZHA class registry refactoring. Less cluttered strict_matching registrations. * Add entities only if there are any. * Migrate rest of ZHA platforms to ZHA registry. * Pylint fixes. --- homeassistant/components/zha/binary_sensor.py | 13 +- .../components/zha/core/registries.py | 65 +- .../components/zha/device_tracker.py | 16 +- homeassistant/components/zha/fan.py | 14 +- homeassistant/components/zha/light.py | 15 +- homeassistant/components/zha/lock.py | 14 +- homeassistant/components/zha/sensor.py | 21 +- homeassistant/components/zha/switch.py | 14 +- tests/components/zha/common.py | 39 +- tests/components/zha/test_channels.py | 8 +- tests/components/zha/test_discover.py | 55 + tests/components/zha/test_registries.py | 84 +- tests/components/zha/zha_devices_list.py | 1874 +++++++++++++++++ 13 files changed, 2152 insertions(+), 80 deletions(-) create mode 100644 tests/components/zha/test_discover.py create mode 100644 tests/components/zha/zha_devices_list.py diff --git a/homeassistant/components/zha/binary_sensor.py b/homeassistant/components/zha/binary_sensor.py index 954fa8b29aa..d8bc1187be8 100644 --- a/homeassistant/components/zha/binary_sensor.py +++ b/homeassistant/components/zha/binary_sensor.py @@ -28,7 +28,7 @@ from .core.const import ( SIGNAL_ATTR_UPDATED, ZHA_DISCOVERY_NEW, ) -from .core.registries import ZHA_ENTITIES, MatchRule +from .core.registries import ZHA_ENTITIES from .entity import ZhaEntity _LOGGER = logging.getLogger(__name__) @@ -85,7 +85,8 @@ async def _async_setup_entities( if entity: entities.append(entity(**discovery_info)) - async_add_entities(entities, update_before_add=True) + if entities: + async_add_entities(entities, update_before_add=True) class BinarySensor(ZhaEntity, BinarySensorDevice): @@ -141,28 +142,28 @@ class BinarySensor(ZhaEntity, BinarySensorDevice): self._state = await self._channel.get_attribute_value(attribute) -@STRICT_MATCH(MatchRule(channel_names={CHANNEL_ACCELEROMETER})) +@STRICT_MATCH(channel_names=CHANNEL_ACCELEROMETER) class Accelerometer(BinarySensor): """ZHA BinarySensor.""" DEVICE_CLASS = DEVICE_CLASS_MOVING -@STRICT_MATCH(MatchRule(channel_names={CHANNEL_OCCUPANCY})) +@STRICT_MATCH(channel_names=CHANNEL_OCCUPANCY) class Occupancy(BinarySensor): """ZHA BinarySensor.""" DEVICE_CLASS = DEVICE_CLASS_OCCUPANCY -@STRICT_MATCH(MatchRule(channel_names={CHANNEL_ON_OFF})) +@STRICT_MATCH(channel_names=CHANNEL_ON_OFF) class Opening(BinarySensor): """ZHA BinarySensor.""" DEVICE_CLASS = DEVICE_CLASS_OPENING -@STRICT_MATCH(MatchRule(channel_names={CHANNEL_ZONE})) +@STRICT_MATCH(channel_names=CHANNEL_ZONE) class IASZone(BinarySensor): """ZHA IAS BinarySensor.""" diff --git a/homeassistant/components/zha/core/registries.py b/homeassistant/components/zha/core/registries.py index f235b459b87..d2ba0243a5c 100644 --- a/homeassistant/components/zha/core/registries.py +++ b/homeassistant/components/zha/core/registries.py @@ -5,7 +5,7 @@ For more details about this component, please refer to the documentation at https://home-assistant.io/integrations/zha/ """ import collections -from typing import Callable, Set +from typing import Callable, Set, Union import attr import bellows.ezsp @@ -171,14 +171,33 @@ def establish_device_mappings(): REMOTE_DEVICE_TYPES[zll.PROFILE_ID].append(zll.DeviceType.SCENE_CONTROLLER) +def set_or_callable(value): + """Convert single str or None to a set. Pass through callables and sets.""" + if value is None: + return frozenset() + if callable(value): + return value + if isinstance(value, (frozenset, set, list)): + return frozenset(value) + return frozenset([str(value)]) + + @attr.s(frozen=True) class MatchRule: """Match a ZHA Entity to a channel name or generic id.""" - channel_names: Set[str] = attr.ib(factory=frozenset, converter=frozenset) - generic_ids: Set[str] = attr.ib(factory=frozenset, converter=frozenset) - manufacturer: str = attr.ib(default=None) - model: str = attr.ib(default=None) + channel_names: Union[Callable, Set[str], str] = attr.ib( + factory=frozenset, converter=set_or_callable + ) + generic_ids: Union[Callable, Set[str], str] = attr.ib( + factory=frozenset, converter=set_or_callable + ) + manufacturers: Union[Callable, Set[str], str] = attr.ib( + factory=frozenset, converter=set_or_callable + ) + models: Union[Callable, Set[str], str] = attr.ib( + factory=frozenset, converter=set_or_callable + ) class ZHAEntityRegistry: @@ -190,7 +209,7 @@ class ZHAEntityRegistry: self._loose_registry = collections.defaultdict(dict) def get_entity( - self, component: str, zha_device, chnls: list, default: CALLABLE_T = None + self, component: str, zha_device, chnls: dict, default: CALLABLE_T = None ) -> CALLABLE_T: """Match a ZHA Channels to a ZHA Entity class.""" for match in self._strict_registry[component]: @@ -200,10 +219,17 @@ class ZHAEntityRegistry: return default def strict_match( - self, component: str, rule: MatchRule + self, + component: str, + channel_names: Union[Callable, Set[str], str] = None, + generic_ids: Union[Callable, Set[str], str] = None, + manufacturers: Union[Callable, Set[str], str] = None, + models: Union[Callable, Set[str], str] = None, ) -> Callable[[CALLABLE_T], CALLABLE_T]: """Decorate a strict match rule.""" + rule = MatchRule(channel_names, generic_ids, manufacturers, models) + def decorator(zha_ent: CALLABLE_T) -> CALLABLE_T: """Register a strict match rule. @@ -215,10 +241,17 @@ class ZHAEntityRegistry: return decorator def loose_match( - self, component: str, rule: MatchRule + self, + component: str, + channel_names: Union[Callable, Set[str], str] = None, + generic_ids: Union[Callable, Set[str], str] = None, + manufacturers: Union[Callable, Set[str], str] = None, + models: Union[Callable, Set[str], str] = None, ) -> Callable[[CALLABLE_T], CALLABLE_T]: """Decorate a loose match rule.""" + rule = MatchRule(channel_names, generic_ids, manufacturers, models) + def decorator(zha_entity: CALLABLE_T) -> CALLABLE_T: """Register a loose match rule. @@ -238,7 +271,7 @@ class ZHAEntityRegistry: return any(self._matched(zha_device, chnls, rule)) @staticmethod - def _matched(zha_device, chnls: list, rule: MatchRule) -> bool: + def _matched(zha_device, chnls: dict, rule: MatchRule) -> list: """Return a list of field matches.""" if not any(attr.asdict(rule).values()): return [False] @@ -252,11 +285,17 @@ class ZHAEntityRegistry: all_generic_ids = {ch.generic_id for ch in chnls} matches.append(rule.generic_ids.issubset(all_generic_ids)) - if rule.manufacturer: - matches.append(zha_device.manufacturer == rule.manufacturer) + if rule.manufacturers: + if callable(rule.manufacturers): + matches.append(rule.manufacturers(zha_device.manufacturer)) + else: + matches.append(zha_device.manufacturer in rule.manufacturers) - if rule.model: - matches.append(zha_device.model == rule.model) + if rule.models: + if callable(rule.models): + matches.append(rule.models(zha_device.model)) + else: + matches.append(zha_device.model in rule.models) return matches diff --git a/homeassistant/components/zha/device_tracker.py b/homeassistant/components/zha/device_tracker.py index e7663b35686..76548935814 100644 --- a/homeassistant/components/zha/device_tracker.py +++ b/homeassistant/components/zha/device_tracker.py @@ -1,4 +1,5 @@ """Support for the ZHA platform.""" +import functools import logging import time @@ -14,9 +15,11 @@ from .core.const import ( SIGNAL_ATTR_UPDATED, ZHA_DISCOVERY_NEW, ) +from .core.registries import ZHA_ENTITIES from .entity import ZhaEntity from .sensor import Battery +STRICT_MATCH = functools.partial(ZHA_ENTITIES.strict_match, DOMAIN) _LOGGER = logging.getLogger(__name__) @@ -47,11 +50,20 @@ async def _async_setup_entities( """Set up the ZHA device trackers.""" entities = [] for discovery_info in discovery_infos: - entities.append(ZHADeviceScannerEntity(**discovery_info)) + zha_dev = discovery_info["zha_device"] + channels = discovery_info["channels"] - async_add_entities(entities, update_before_add=True) + entity = ZHA_ENTITIES.get_entity( + DOMAIN, zha_dev, channels, ZHADeviceScannerEntity + ) + if entity: + entities.append(entity(**discovery_info)) + + if entities: + async_add_entities(entities, update_before_add=True) +@STRICT_MATCH(channel_names=CHANNEL_POWER_CONFIGURATION) class ZHADeviceScannerEntity(ScannerEntity, ZhaEntity): """Represent a tracked device.""" diff --git a/homeassistant/components/zha/fan.py b/homeassistant/components/zha/fan.py index bccdf260a11..f489447e530 100644 --- a/homeassistant/components/zha/fan.py +++ b/homeassistant/components/zha/fan.py @@ -1,4 +1,5 @@ """Fans on Zigbee Home Automation networks.""" +import functools import logging from homeassistant.components.fan import ( @@ -20,6 +21,7 @@ from .core.const import ( SIGNAL_ATTR_UPDATED, ZHA_DISCOVERY_NEW, ) +from .core.registries import ZHA_ENTITIES from .entity import ZhaEntity _LOGGER = logging.getLogger(__name__) @@ -45,6 +47,7 @@ SPEED_LIST = [ VALUE_TO_SPEED = dict(enumerate(SPEED_LIST)) SPEED_TO_VALUE = {speed: i for i, speed in enumerate(SPEED_LIST)} +STRICT_MATCH = functools.partial(ZHA_ENTITIES.strict_match, DOMAIN) async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): @@ -79,11 +82,18 @@ async def _async_setup_entities( """Set up the ZHA fans.""" entities = [] for discovery_info in discovery_infos: - entities.append(ZhaFan(**discovery_info)) + zha_dev = discovery_info["zha_device"] + channels = discovery_info["channels"] - async_add_entities(entities, update_before_add=True) + entity = ZHA_ENTITIES.get_entity(DOMAIN, zha_dev, channels, ZhaFan) + if entity: + entities.append(entity(**discovery_info)) + + if entities: + async_add_entities(entities, update_before_add=True) +@STRICT_MATCH(channel_names=CHANNEL_FAN) class ZhaFan(ZhaEntity, FanEntity): """Representation of a ZHA fan.""" diff --git a/homeassistant/components/zha/light.py b/homeassistant/components/zha/light.py index 08d74f9fdb3..eb7d3297b43 100644 --- a/homeassistant/components/zha/light.py +++ b/homeassistant/components/zha/light.py @@ -1,5 +1,6 @@ """Lights on Zigbee Home Automation networks.""" from datetime import timedelta +import functools import logging from zigpy.zcl.foundation import Status @@ -21,6 +22,7 @@ from .core.const import ( SIGNAL_SET_LEVEL, ZHA_DISCOVERY_NEW, ) +from .core.registries import ZHA_ENTITIES from .entity import ZhaEntity _LOGGER = logging.getLogger(__name__) @@ -36,6 +38,7 @@ UPDATE_COLORLOOP_HUE = 0x8 UNSUPPORTED_ATTRIBUTE = 0x86 SCAN_INTERVAL = timedelta(minutes=60) +STRICT_MATCH = functools.partial(ZHA_ENTITIES.strict_match, light.DOMAIN) PARALLEL_UPDATES = 5 @@ -71,12 +74,18 @@ async def _async_setup_entities( """Set up the ZHA lights.""" entities = [] for discovery_info in discovery_infos: - zha_light = Light(**discovery_info) - entities.append(zha_light) + zha_dev = discovery_info["zha_device"] + channels = discovery_info["channels"] - async_add_entities(entities, update_before_add=True) + entity = ZHA_ENTITIES.get_entity(light.DOMAIN, zha_dev, channels, Light) + if entity: + entities.append(entity(**discovery_info)) + + if entities: + async_add_entities(entities, update_before_add=True) +@STRICT_MATCH(channel_names=CHANNEL_ON_OFF) class Light(ZhaEntity, light.Light): """Representation of a ZHA or ZLL light.""" diff --git a/homeassistant/components/zha/lock.py b/homeassistant/components/zha/lock.py index 2458bf4be5b..bf82252246c 100644 --- a/homeassistant/components/zha/lock.py +++ b/homeassistant/components/zha/lock.py @@ -1,4 +1,5 @@ """Locks on Zigbee Home Automation networks.""" +import functools import logging from zigpy.zcl.foundation import Status @@ -19,6 +20,7 @@ from .core.const import ( SIGNAL_ATTR_UPDATED, ZHA_DISCOVERY_NEW, ) +from .core.registries import ZHA_ENTITIES from .entity import ZhaEntity _LOGGER = logging.getLogger(__name__) @@ -26,6 +28,7 @@ _LOGGER = logging.getLogger(__name__) """ The first state is Zigbee 'Not fully locked' """ STATE_LIST = [STATE_UNLOCKED, STATE_LOCKED, STATE_UNLOCKED] +STRICT_MATCH = functools.partial(ZHA_ENTITIES.strict_match, DOMAIN) VALUE_TO_STATE = dict(enumerate(STATE_LIST)) @@ -62,11 +65,18 @@ async def _async_setup_entities( """Set up the ZHA locks.""" entities = [] for discovery_info in discovery_infos: - entities.append(ZhaDoorLock(**discovery_info)) + zha_dev = discovery_info["zha_device"] + channels = discovery_info["channels"] - async_add_entities(entities, update_before_add=True) + entity = ZHA_ENTITIES.get_entity(DOMAIN, zha_dev, channels, ZhaDoorLock) + if entity: + entities.append(entity(**discovery_info)) + + if entities: + async_add_entities(entities, update_before_add=True) +@STRICT_MATCH(channel_names=CHANNEL_DOORLOCK) class ZhaDoorLock(ZhaEntity, LockDevice): """Representation of a ZHA lock.""" diff --git a/homeassistant/components/zha/sensor.py b/homeassistant/components/zha/sensor.py index 26dc25c71dc..2d39d562bf5 100644 --- a/homeassistant/components/zha/sensor.py +++ b/homeassistant/components/zha/sensor.py @@ -30,7 +30,7 @@ from .core.const import ( SIGNAL_STATE_ATTR, ZHA_DISCOVERY_NEW, ) -from .core.registries import SMARTTHINGS_HUMIDITY_CLUSTER, ZHA_ENTITIES, MatchRule +from .core.registries import SMARTTHINGS_HUMIDITY_CLUSTER, ZHA_ENTITIES from .entity import ZhaEntity PARALLEL_UPDATES = 5 @@ -90,7 +90,8 @@ async def _async_setup_entities( for discovery_info in discovery_infos: entities.append(await make_sensor(discovery_info)) - async_add_entities(entities, update_before_add=True) + if entities: + async_add_entities(entities, update_before_add=True) async def make_sensor(discovery_info): @@ -175,7 +176,7 @@ class Sensor(ZhaEntity): return round(float(value * self._multiplier) / self._divisor) -@STRICT_MATCH(MatchRule(channel_names={CHANNEL_POWER_CONFIGURATION})) +@STRICT_MATCH(channel_names=CHANNEL_POWER_CONFIGURATION) class Battery(Sensor): """Battery sensor of power configuration cluster.""" @@ -203,7 +204,7 @@ class Battery(Sensor): return state_attrs -@STRICT_MATCH(MatchRule(channel_names={CHANNEL_ELECTRICAL_MEASUREMENT})) +@STRICT_MATCH(channel_names=CHANNEL_ELECTRICAL_MEASUREMENT) class ElectricalMeasurement(Sensor): """Active power measurement.""" @@ -221,8 +222,8 @@ class ElectricalMeasurement(Sensor): return round(value * self._channel.multiplier / self._channel.divisor) -@STRICT_MATCH(MatchRule(generic_ids={CHANNEL_ST_HUMIDITY_CLUSTER})) -@STRICT_MATCH(MatchRule(channel_names={CHANNEL_HUMIDITY})) +@STRICT_MATCH(generic_ids=CHANNEL_ST_HUMIDITY_CLUSTER) +@STRICT_MATCH(channel_names=CHANNEL_HUMIDITY) class Humidity(Sensor): """Humidity sensor.""" @@ -231,7 +232,7 @@ class Humidity(Sensor): _unit = "%" -@STRICT_MATCH(MatchRule(channel_names={CHANNEL_ILLUMINANCE})) +@STRICT_MATCH(channel_names=CHANNEL_ILLUMINANCE) class Illuminance(Sensor): """Illuminance Sensor.""" @@ -244,7 +245,7 @@ class Illuminance(Sensor): return round(pow(10, ((value - 1) / 10000)), 1) -@STRICT_MATCH(MatchRule(channel_names={CHANNEL_SMARTENERGY_METERING})) +@STRICT_MATCH(channel_names=CHANNEL_SMARTENERGY_METERING) class SmartEnergyMetering(Sensor): """Metering sensor.""" @@ -260,7 +261,7 @@ class SmartEnergyMetering(Sensor): return self._channel.unit_of_measurement -@STRICT_MATCH(MatchRule(channel_names={CHANNEL_PRESSURE})) +@STRICT_MATCH(channel_names=CHANNEL_PRESSURE) class Pressure(Sensor): """Pressure sensor.""" @@ -269,7 +270,7 @@ class Pressure(Sensor): _unit = "hPa" -@STRICT_MATCH(MatchRule(channel_names={CHANNEL_TEMPERATURE})) +@STRICT_MATCH(channel_names=CHANNEL_TEMPERATURE) class Temperature(Sensor): """Temperature Sensor.""" diff --git a/homeassistant/components/zha/switch.py b/homeassistant/components/zha/switch.py index 03296e8a553..cbd29925f62 100644 --- a/homeassistant/components/zha/switch.py +++ b/homeassistant/components/zha/switch.py @@ -1,4 +1,5 @@ """Switches on Zigbee Home Automation networks.""" +import functools import logging from zigpy.zcl.foundation import Status @@ -15,9 +16,11 @@ from .core.const import ( SIGNAL_ATTR_UPDATED, ZHA_DISCOVERY_NEW, ) +from .core.registries import ZHA_ENTITIES from .entity import ZhaEntity _LOGGER = logging.getLogger(__name__) +STRICT_MATCH = functools.partial(ZHA_ENTITIES.strict_match, DOMAIN) async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): @@ -52,11 +55,18 @@ async def _async_setup_entities( """Set up the ZHA switches.""" entities = [] for discovery_info in discovery_infos: - entities.append(Switch(**discovery_info)) + zha_dev = discovery_info["zha_device"] + channels = discovery_info["channels"] - async_add_entities(entities, update_before_add=True) + entity = ZHA_ENTITIES.get_entity(DOMAIN, zha_dev, channels, Switch) + if entity: + entities.append(entity(**discovery_info)) + + if entities: + async_add_entities(entities, update_before_add=True) +@STRICT_MATCH(channel_names=CHANNEL_ON_OFF) class Switch(ZhaEntity, SwitchDevice): """ZHA switch.""" diff --git a/tests/components/zha/common.py b/tests/components/zha/common.py index 57fb26db7f0..06712e638f6 100644 --- a/tests/components/zha/common.py +++ b/tests/components/zha/common.py @@ -36,10 +36,10 @@ APPLICATION = FakeApplication() class FakeEndpoint: """Fake endpoint for moking zigpy.""" - def __init__(self, manufacturer, model): + def __init__(self, manufacturer, model, epid=1): """Init fake endpoint.""" self.device = None - self.endpoint_id = 1 + self.endpoint_id = epid self.in_clusters = {} self.out_clusters = {} self._cluster_attr = {} @@ -97,21 +97,23 @@ class FakeDevice: self.remove_from_group = CoroutineMock() -def make_device( - in_cluster_ids, out_cluster_ids, device_type, ieee, manufacturer, model -): +def make_device(endpoints, ieee, manufacturer, model): """Make a fake device using the specified cluster classes.""" device = FakeDevice(ieee, manufacturer, model) - endpoint = FakeEndpoint(manufacturer, model) - endpoint.device = device - device.endpoints[endpoint.endpoint_id] = endpoint - endpoint.device_type = device_type + for epid, ep in endpoints.items(): + endpoint = FakeEndpoint(manufacturer, model, epid) + endpoint.device = device + device.endpoints[epid] = endpoint + endpoint.device_type = ep["device_type"] + profile_id = ep.get("profile_id") + if profile_id: + endpoint.profile_id = profile_id - for cluster_id in in_cluster_ids: - endpoint.add_input_cluster(cluster_id) + for cluster_id in ep.get("in_clusters", []): + endpoint.add_input_cluster(cluster_id) - for cluster_id in out_cluster_ids: - endpoint.add_output_cluster(cluster_id) + for cluster_id in ep.get("out_clusters", []): + endpoint.add_output_cluster(cluster_id) return device @@ -136,7 +138,16 @@ async def async_init_zigpy_device( happens when the device is paired to the network for the first time. """ device = make_device( - in_cluster_ids, out_cluster_ids, device_type, ieee, manufacturer, model + { + 1: { + "in_clusters": in_cluster_ids, + "out_clusters": out_cluster_ids, + "device_type": device_type, + } + }, + ieee, + manufacturer, + model, ) if is_new_join: await gateway.async_device_initialized(device) diff --git a/tests/components/zha/test_channels.py b/tests/components/zha/test_channels.py index 3be3aaf0930..557cc0f2c5c 100644 --- a/tests/components/zha/test_channels.py +++ b/tests/components/zha/test_channels.py @@ -67,9 +67,7 @@ def nwk(): async def test_in_channel_config(cluster_id, bind_count, attrs, zha_gateway, hass): """Test ZHA core channel configuration for input clusters.""" zigpy_dev = make_device( - [cluster_id], - [], - 0x1234, + {1: {"in_clusters": [cluster_id], "out_clusters": [], "device_type": 0x1234}}, "00:11:22:33:44:55:66:77", "test manufacturer", "test model", @@ -125,9 +123,7 @@ async def test_in_channel_config(cluster_id, bind_count, attrs, zha_gateway, has async def test_out_channel_config(cluster_id, bind_count, zha_gateway, hass): """Test ZHA core channel configuration for output clusters.""" zigpy_dev = make_device( - [], - [cluster_id], - 0x1234, + {1: {"out_clusters": [cluster_id], "in_clusters": [], "device_type": 0x1234}}, "00:11:22:33:44:55:66:77", "test manufacturer", "test model", diff --git a/tests/components/zha/test_discover.py b/tests/components/zha/test_discover.py new file mode 100644 index 00000000000..91805acc448 --- /dev/null +++ b/tests/components/zha/test_discover.py @@ -0,0 +1,55 @@ +"""Test zha device discovery.""" + +import asyncio +from unittest import mock + +import pytest + +from homeassistant.components.zha.core.channels import EventRelayChannel +import homeassistant.components.zha.core.const as zha_const +import homeassistant.components.zha.core.discovery as disc +import homeassistant.components.zha.core.gateway as core_zha_gw + +from .common import make_device +from .zha_devices_list import DEVICES + + +@pytest.mark.parametrize("device", DEVICES) +async def test_devices(device, zha_gateway: core_zha_gw.ZHAGateway, hass, config_entry): + """Test device discovery.""" + + zigpy_device = make_device( + device["endpoints"], + "00:11:22:33:44:55:66:77", + device["manufacturer"], + device["model"], + ) + + with mock.patch( + "homeassistant.components.zha.core.discovery._async_create_cluster_channel", + wraps=disc._async_create_cluster_channel, + ) as cr_ch: + await zha_gateway.async_device_restored(zigpy_device) + await hass.async_block_till_done() + tasks = [ + hass.config_entries.async_forward_entry_setup(config_entry, component) + for component in zha_const.COMPONENTS + ] + await asyncio.gather(*tasks) + + await hass.async_block_till_done() + + entity_ids = hass.states.async_entity_ids() + await hass.async_block_till_done() + zha_entities = { + ent for ent in entity_ids if ent.split(".")[0] in zha_const.COMPONENTS + } + + event_channels = { + arg[0].cluster_id + for arg, kwarg in cr_ch.call_args_list + if kwarg.get("channel_class") == EventRelayChannel + } + + assert zha_entities == set(device["entities"]) + assert event_channels == set(device["event_channels"]) diff --git a/tests/components/zha/test_registries.py b/tests/components/zha/test_registries.py index a0eef355229..9f77330dd55 100644 --- a/tests/components/zha/test_registries.py +++ b/tests/components/zha/test_registries.py @@ -59,24 +59,68 @@ def channels(): True, ), # manufacturer matching - (registries.MatchRule(manufacturer="no match"), False), - (registries.MatchRule(manufacturer=MANUFACTURER), True), - (registries.MatchRule(model=MODEL), True), - (registries.MatchRule(model="no match"), False), + (registries.MatchRule(manufacturers="no match"), False), + (registries.MatchRule(manufacturers=MANUFACTURER), True), + (registries.MatchRule(models=MODEL), True), + (registries.MatchRule(models="no match"), False), # match everything ( registries.MatchRule( generic_ids={"channel_0x0006", "channel_0x0008"}, channel_names={"on_off", "level"}, - manufacturer=MANUFACTURER, - model=MODEL, + manufacturers=MANUFACTURER, + models=MODEL, ), True, ), + ( + registries.MatchRule( + channel_names="on_off", manufacturers={"random manuf", MANUFACTURER} + ), + True, + ), + ( + registries.MatchRule( + channel_names="on_off", manufacturers={"random manuf", "Another manuf"} + ), + False, + ), + ( + registries.MatchRule( + channel_names="on_off", manufacturers=lambda x: x == MANUFACTURER + ), + True, + ), + ( + registries.MatchRule( + channel_names="on_off", manufacturers=lambda x: x != MANUFACTURER + ), + False, + ), + ( + registries.MatchRule( + channel_names="on_off", models={"random model", MODEL} + ), + True, + ), + ( + registries.MatchRule( + channel_names="on_off", models={"random model", "Another model"} + ), + False, + ), + ( + registries.MatchRule(channel_names="on_off", models=lambda x: x == MODEL), + True, + ), + ( + registries.MatchRule(channel_names="on_off", models=lambda x: x != MODEL), + False, + ), ], ) def test_registry_matching(rule, matched, zha_device, channels): - """Test empty rule matching.""" + """Test strict rule matching.""" reg = registries.ZHAEntityRegistry() assert reg._strict_matched(zha_device, channels, rule) is matched @@ -92,22 +136,22 @@ def test_registry_matching(rule, matched, zha_device, channels): (registries.MatchRule(channel_names={"on_off", "level"}), True), (registries.MatchRule(channel_names={"on_off", "level", "no match"}), False), ( - registries.MatchRule(channel_names={"on_off", "level"}, model="no match"), + registries.MatchRule(channel_names={"on_off", "level"}, models="no match"), True, ), ( registries.MatchRule( channel_names={"on_off", "level"}, - model="no match", - manufacturer="no match", + models="no match", + manufacturers="no match", ), True, ), ( registries.MatchRule( channel_names={"on_off", "level"}, - model="no match", - manufacturer=MANUFACTURER, + models="no match", + manufacturers=MANUFACTURER, ), True, ), @@ -124,14 +168,14 @@ def test_registry_matching(rule, matched, zha_device, channels): ( registries.MatchRule( generic_ids={"channel_0x0006", "channel_0x0008", "channel_0x0009"}, - model="mo match", + models="mo match", ), False, ), ( registries.MatchRule( generic_ids={"channel_0x0006", "channel_0x0008", "channel_0x0009"}, - model=MODEL, + models=MODEL, ), True, ), @@ -143,17 +187,17 @@ def test_registry_matching(rule, matched, zha_device, channels): True, ), # manufacturer matching - (registries.MatchRule(manufacturer="no match"), False), - (registries.MatchRule(manufacturer=MANUFACTURER), True), - (registries.MatchRule(model=MODEL), True), - (registries.MatchRule(model="no match"), False), + (registries.MatchRule(manufacturers="no match"), False), + (registries.MatchRule(manufacturers=MANUFACTURER), True), + (registries.MatchRule(models=MODEL), True), + (registries.MatchRule(models="no match"), False), # match everything ( registries.MatchRule( generic_ids={"channel_0x0006", "channel_0x0008"}, channel_names={"on_off", "level"}, - manufacturer=MANUFACTURER, - model=MODEL, + manufacturers=MANUFACTURER, + models=MODEL, ), True, ), diff --git a/tests/components/zha/zha_devices_list.py b/tests/components/zha/zha_devices_list.py new file mode 100644 index 00000000000..d5875edc9e2 --- /dev/null +++ b/tests/components/zha/zha_devices_list.py @@ -0,0 +1,1874 @@ +"""Example Zigbee Devices.""" + +DEVICES = [ + { + "endpoints": { + "1": { + "device_type": 2080, + "endpoint_id": 1, + "in_clusters": [0, 3, 4096, 64716], + "out_clusters": [3, 4, 6, 8, 4096, 64716], + "profile_id": 260, + } + }, + "entities": [], + "event_channels": [6, 8], + "manufacturer": "ADUROLIGHT", + "model": "Adurolight_NCC", + }, + { + "endpoints": { + "5": { + "device_type": 1026, + "endpoint_id": 5, + "in_clusters": [0, 1, 3, 32, 1026, 1280, 2821], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.bosch_isw_zpr1_wp13_77665544_ias_zone", + "sensor.bosch_isw_zpr1_wp13_77665544_power", + "sensor.bosch_isw_zpr1_wp13_77665544_temperature", + ], + "event_channels": [], + "manufacturer": "Bosch", + "model": "ISW-ZPR1-WP13", + }, + { + "endpoints": { + "1": { + "device_type": 1, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 32, 2821], + "out_clusters": [3, 6, 8, 25], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.centralite_3130_77665544_on_off", + "sensor.centralite_3130_77665544_power", + ], + "event_channels": [6, 8], + "manufacturer": "CentraLite", + "model": "3130", + }, + { + "endpoints": { + "1": { + "device_type": 81, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 1794, 2820, 2821, 64515], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": [ + "sensor.centralite_3210_l_77665544_smartenergy_metering", + "sensor.centralite_3210_l_77665544_electrical_measurement", + "switch.centralite_3210_l_77665544_on_off", + ], + "event_channels": [], + "manufacturer": "CentraLite", + "model": "3210-L", + }, + { + "endpoints": { + "1": { + "device_type": 770, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 32, 1026, 2821, 64581], + "out_clusters": [3, 25], + "profile_id": 260, + } + }, + "entities": [ + "sensor.centralite_3310_s_77665544_power", + "sensor.centralite_3310_s_77665544_temperature", + "sensor.centralite_3310_s_77665544_manufacturer_specific", + ], + "event_channels": [], + "manufacturer": "CentraLite", + "model": "3310-S", + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 32, 1026, 1280, 2821], + "out_clusters": [25], + "profile_id": 260, + }, + "2": { + "device_type": 12, + "endpoint_id": 2, + "in_clusters": [0, 3, 2821, 64527], + "out_clusters": [3], + "profile_id": 49887, + }, + }, + "entities": [ + "binary_sensor.centralite_3315_s_77665544_ias_zone", + "sensor.centralite_3315_s_77665544_temperature", + "sensor.centralite_3315_s_77665544_power", + ], + "event_channels": [], + "manufacturer": "CentraLite", + "model": "3315-S", + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 32, 1026, 1280, 2821], + "out_clusters": [25], + "profile_id": 260, + }, + "2": { + "device_type": 12, + "endpoint_id": 2, + "in_clusters": [0, 3, 2821, 64527], + "out_clusters": [3], + "profile_id": 49887, + }, + }, + "entities": [ + "binary_sensor.centralite_3320_l_77665544_ias_zone", + "sensor.centralite_3320_l_77665544_temperature", + "sensor.centralite_3320_l_77665544_power", + ], + "event_channels": [], + "manufacturer": "CentraLite", + "model": "3320-L", + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 32, 1026, 1280, 2821], + "out_clusters": [25], + "profile_id": 260, + }, + "2": { + "device_type": 263, + "endpoint_id": 2, + "in_clusters": [0, 3, 2821, 64582], + "out_clusters": [3], + "profile_id": 49887, + }, + }, + "entities": [ + "binary_sensor.centralite_3326_l_77665544_ias_zone", + "sensor.centralite_3326_l_77665544_temperature", + "sensor.centralite_3326_l_77665544_power", + ], + "event_channels": [], + "manufacturer": "CentraLite", + "model": "3326-L", + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 32, 1026, 1280, 2821], + "out_clusters": [25], + "profile_id": 260, + }, + "2": { + "device_type": 263, + "endpoint_id": 2, + "in_clusters": [0, 3, 1030, 2821], + "out_clusters": [3], + "profile_id": 260, + }, + }, + "entities": [ + "binary_sensor.centralite_motion_sensor_a_77665544_occupancy", + "binary_sensor.centralite_motion_sensor_a_77665544_ias_zone", + "sensor.centralite_motion_sensor_a_77665544_temperature", + "sensor.centralite_motion_sensor_a_77665544_power", + ], + "event_channels": [], + "manufacturer": "CentraLite", + "model": "Motion Sensor-A", + }, + { + "endpoints": { + "1": { + "device_type": 81, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 1794], + "out_clusters": [0], + "profile_id": 260, + }, + "4": { + "device_type": 9, + "endpoint_id": 4, + "in_clusters": [], + "out_clusters": [25], + "profile_id": 260, + }, + }, + "entities": [ + "sensor.climaxtechnology_psmp5_00_00_02_02tc_77665544_smartenergy_metering", + "switch.climaxtechnology_psmp5_00_00_02_02tc_77665544_on_off", + ], + "event_channels": [], + "manufacturer": "ClimaxTechnology", + "model": "PSMP5_00.00.02.02TC", + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 3, 1280, 1282], + "out_clusters": [0], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.climaxtechnology_sd8sc_00_00_03_12tc_77665544_ias_zone" + ], + "event_channels": [], + "manufacturer": "ClimaxTechnology", + "model": "SD8SC_00.00.03.12TC", + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 3, 1280], + "out_clusters": [0], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.climaxtechnology_ws15_00_00_03_03tc_77665544_ias_zone" + ], + "event_channels": [], + "manufacturer": "ClimaxTechnology", + "model": "WS15_00.00.03.03TC", + }, + { + "endpoints": { + "11": { + "device_type": 528, + "endpoint_id": 11, + "in_clusters": [0, 3, 4, 5, 6, 8, 768], + "out_clusters": [], + "profile_id": 49246, + }, + "13": { + "device_type": 57694, + "endpoint_id": 13, + "in_clusters": [4096], + "out_clusters": [4096], + "profile_id": 49246, + }, + }, + "entities": [ + "light.feibit_inc_co_fb56_zcw08ku1_1_77665544_level_light_color_on_off" + ], + "event_channels": [], + "manufacturer": "Feibit Inc co.", + "model": "FB56-ZCW08KU1.1", + }, + { + "endpoints": { + "1": { + "device_type": 1027, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 4, 9, 1280, 1282], + "out_clusters": [3, 25], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.heiman_warningdevice_77665544_ias_zone", + "sensor.heiman_warningdevice_77665544_power", + ], + "event_channels": [], + "manufacturer": "Heiman", + "model": "WarningDevice", + }, + { + "endpoints": { + "6": { + "device_type": 1026, + "endpoint_id": 6, + "in_clusters": [0, 1, 3, 32, 1024, 1026, 1280], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": [ + "sensor.hivehome_com_mot003_77665544_temperature", + "sensor.hivehome_com_mot003_77665544_power", + "sensor.hivehome_com_mot003_77665544_illuminance", + "binary_sensor.hivehome_com_mot003_77665544_ias_zone", + ], + "event_channels": [], + "manufacturer": "HiveHome.com", + "model": "MOT003", + }, + { + "endpoints": { + "1": { + "device_type": 268, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 8, 768, 4096, 64636], + "out_clusters": [5, 25, 32, 4096], + "profile_id": 260, + }, + "242": { + "device_type": 97, + "endpoint_id": 242, + "in_clusters": [33], + "out_clusters": [33], + "profile_id": 41440, + }, + }, + "entities": [ + "light.ikea_of_sweden_tradfri_bulb_e12_ws_opal_600lm_77665544_level_light_color_on_off" + ], + "event_channels": [], + "manufacturer": "IKEA of Sweden", + "model": "TRADFRI bulb E12 WS opal 600lm", + }, + { + "endpoints": { + "1": { + "device_type": 512, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 8, 768, 2821, 4096], + "out_clusters": [5, 25, 32, 4096], + "profile_id": 49246, + } + }, + "entities": [ + "light.ikea_of_sweden_tradfri_bulb_e26_cws_opal_600lm_77665544_level_light_color_on_off" + ], + "event_channels": [], + "manufacturer": "IKEA of Sweden", + "model": "TRADFRI bulb E26 CWS opal 600lm", + }, + { + "endpoints": { + "1": { + "device_type": 256, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 8, 2821, 4096], + "out_clusters": [5, 25, 32, 4096], + "profile_id": 49246, + } + }, + "entities": [ + "light.ikea_of_sweden_tradfri_bulb_e26_w_opal_1000lm_77665544_level_on_off" + ], + "event_channels": [], + "manufacturer": "IKEA of Sweden", + "model": "TRADFRI bulb E26 W opal 1000lm", + }, + { + "endpoints": { + "1": { + "device_type": 544, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 8, 768, 2821, 4096], + "out_clusters": [5, 25, 32, 4096], + "profile_id": 49246, + } + }, + "entities": [ + "light.ikea_of_sweden_tradfri_bulb_e26_ws_opal_980lm_77665544_level_light_color_on_off" + ], + "event_channels": [], + "manufacturer": "IKEA of Sweden", + "model": "TRADFRI bulb E26 WS opal 980lm", + }, + { + "endpoints": { + "1": { + "device_type": 256, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 8, 2821, 4096], + "out_clusters": [5, 25, 32, 4096], + "profile_id": 260, + } + }, + "entities": [ + "light.ikea_of_sweden_tradfri_bulb_e26_opal_1000lm_77665544_level_on_off" + ], + "event_channels": [], + "manufacturer": "IKEA of Sweden", + "model": "TRADFRI bulb E26 opal 1000lm", + }, + { + "endpoints": { + "1": { + "device_type": 266, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 64636], + "out_clusters": [5, 25, 32], + "profile_id": 260, + } + }, + "entities": ["switch.ikea_of_sweden_tradfri_control_outlet_77665544_on_off"], + "event_channels": [], + "manufacturer": "IKEA of Sweden", + "model": "TRADFRI control outlet", + }, + { + "endpoints": { + "1": { + "device_type": 2128, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 9, 2821, 4096], + "out_clusters": [3, 4, 6, 25, 4096], + "profile_id": 49246, + } + }, + "entities": [ + "binary_sensor.ikea_of_sweden_tradfri_motion_sensor_77665544_on_off", + "sensor.ikea_of_sweden_tradfri_motion_sensor_77665544_power", + ], + "event_channels": [6], + "manufacturer": "IKEA of Sweden", + "model": "TRADFRI motion sensor", + }, + { + "endpoints": { + "1": { + "device_type": 2080, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 9, 32, 4096, 64636], + "out_clusters": [3, 4, 6, 8, 25, 258, 4096], + "profile_id": 260, + } + }, + "entities": ["sensor.ikea_of_sweden_tradfri_on_off_switch_77665544_power"], + "event_channels": [6, 8], + "manufacturer": "IKEA of Sweden", + "model": "TRADFRI on/off switch", + }, + { + "endpoints": { + "1": { + "device_type": 2096, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 9, 2821, 4096], + "out_clusters": [3, 4, 5, 6, 8, 25, 4096], + "profile_id": 49246, + } + }, + "entities": ["sensor.ikea_of_sweden_tradfri_remote_control_77665544_power"], + "event_channels": [6, 8], + "manufacturer": "IKEA of Sweden", + "model": "TRADFRI remote control", + }, + { + "endpoints": { + "1": { + "device_type": 8, + "endpoint_id": 1, + "in_clusters": [0, 3, 9, 2821, 4096, 64636], + "out_clusters": [25, 32, 4096], + "profile_id": 260, + }, + "242": { + "device_type": 97, + "endpoint_id": 242, + "in_clusters": [33], + "out_clusters": [33], + "profile_id": 41440, + }, + }, + "entities": [], + "event_channels": [], + "manufacturer": "IKEA of Sweden", + "model": "TRADFRI signal repeater", + }, + { + "endpoints": { + "1": { + "device_type": 2064, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 9, 2821, 4096], + "out_clusters": [3, 4, 6, 8, 25, 4096], + "profile_id": 260, + } + }, + "entities": ["sensor.ikea_of_sweden_tradfri_wireless_dimmer_77665544_power"], + "event_channels": [6, 8], + "manufacturer": "IKEA of Sweden", + "model": "TRADFRI wireless dimmer", + }, + { + "endpoints": { + "1": { + "device_type": 257, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 8, 1794, 2821], + "out_clusters": [10, 25], + "profile_id": 260, + }, + "2": { + "device_type": 260, + "endpoint_id": 2, + "in_clusters": [0, 3, 2821], + "out_clusters": [3, 6, 8], + "profile_id": 260, + }, + }, + "entities": [ + "sensor.jasco_products_45852_77665544_smartenergy_metering", + "light.jasco_products_45852_77665544_level_on_off", + ], + "event_channels": [6, 8], + "manufacturer": "Jasco Products", + "model": "45852", + }, + { + "endpoints": { + "1": { + "device_type": 256, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 1794, 2821], + "out_clusters": [10, 25], + "profile_id": 260, + }, + "2": { + "device_type": 259, + "endpoint_id": 2, + "in_clusters": [0, 3, 2821], + "out_clusters": [3, 6], + "profile_id": 260, + }, + }, + "entities": [ + "sensor.jasco_products_45856_77665544_smartenergy_metering", + "switch.jasco_products_45856_77665544_on_off", + "light.jasco_products_45856_77665544_on_off", + ], + "event_channels": [6], + "manufacturer": "Jasco Products", + "model": "45856", + }, + { + "endpoints": { + "1": { + "device_type": 257, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 8, 1794, 2821], + "out_clusters": [10, 25], + "profile_id": 260, + }, + "2": { + "device_type": 260, + "endpoint_id": 2, + "in_clusters": [0, 3, 2821], + "out_clusters": [3, 6, 8], + "profile_id": 260, + }, + }, + "entities": [ + "sensor.jasco_products_45857_77665544_smartenergy_metering", + "light.jasco_products_45857_77665544_level_on_off", + ], + "event_channels": [6, 8], + "manufacturer": "Jasco Products", + "model": "45857", + }, + { + "endpoints": { + "1": { + "device_type": 3, + "endpoint_id": 1, + "in_clusters": [ + 0, + 1, + 3, + 4, + 5, + 6, + 8, + 32, + 1026, + 1027, + 2821, + 64513, + 64514, + ], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.keen_home_inc_sv02_610_mp_1_3_77665544_manufacturer_specific", + "sensor.keen_home_inc_sv02_610_mp_1_3_77665544_pressure", + "sensor.keen_home_inc_sv02_610_mp_1_3_77665544_temperature", + "sensor.keen_home_inc_sv02_610_mp_1_3_77665544_power", + "light.keen_home_inc_sv02_610_mp_1_3_77665544_level_on_off", + ], + "event_channels": [], + "manufacturer": "Keen Home Inc", + "model": "SV02-610-MP-1.3", + }, + { + "endpoints": { + "1": { + "device_type": 3, + "endpoint_id": 1, + "in_clusters": [ + 0, + 1, + 3, + 4, + 5, + 6, + 8, + 32, + 1026, + 1027, + 2821, + 64513, + 64514, + ], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.keen_home_inc_sv02_612_mp_1_2_77665544_manufacturer_specific", + "sensor.keen_home_inc_sv02_612_mp_1_2_77665544_temperature", + "sensor.keen_home_inc_sv02_612_mp_1_2_77665544_power", + "sensor.keen_home_inc_sv02_612_mp_1_2_77665544_pressure", + "light.keen_home_inc_sv02_612_mp_1_2_77665544_level_on_off", + ], + "event_channels": [], + "manufacturer": "Keen Home Inc", + "model": "SV02-612-MP-1.2", + }, + { + "endpoints": { + "1": { + "device_type": 3, + "endpoint_id": 1, + "in_clusters": [ + 0, + 1, + 3, + 4, + 5, + 6, + 8, + 32, + 1026, + 1027, + 2821, + 64513, + 64514, + ], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.keen_home_inc_sv02_612_mp_1_3_77665544_manufacturer_specific", + "sensor.keen_home_inc_sv02_612_mp_1_3_77665544_pressure", + "sensor.keen_home_inc_sv02_612_mp_1_3_77665544_power", + "sensor.keen_home_inc_sv02_612_mp_1_3_77665544_temperature", + "light.keen_home_inc_sv02_612_mp_1_3_77665544_level_on_off", + ], + "event_channels": [], + "manufacturer": "Keen Home Inc", + "model": "SV02-612-MP-1.3", + }, + { + "endpoints": { + "1": { + "device_type": 14, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 8, 514], + "out_clusters": [3, 25], + "profile_id": 260, + } + }, + "entities": [ + "fan.king_of_fans_inc_hbuniversalcfremote_77665544_fan", + "switch.king_of_fans_inc_hbuniversalcfremote_77665544_on_off", + ], + "event_channels": [], + "manufacturer": "King Of Fans, Inc.", + "model": "HBUniversalCFRemote", + }, + { + "endpoints": { + "1": { + "device_type": 258, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 8, 768, 2821, 64513], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": ["light.ledvance_a19_rgbw_77665544_level_light_color_on_off"], + "event_channels": [], + "manufacturer": "LEDVANCE", + "model": "A19 RGBW", + }, + { + "endpoints": { + "1": { + "device_type": 258, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 8, 768, 2821, 64513], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": ["light.ledvance_flex_rgbw_77665544_level_light_color_on_off"], + "event_channels": [], + "manufacturer": "LEDVANCE", + "model": "FLEX RGBW", + }, + { + "endpoints": { + "1": { + "device_type": 81, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 2821, 64513, 64520], + "out_clusters": [3, 25], + "profile_id": 260, + } + }, + "entities": ["switch.ledvance_plug_77665544_on_off"], + "event_channels": [], + "manufacturer": "LEDVANCE", + "model": "PLUG", + }, + { + "endpoints": { + "1": { + "device_type": 258, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 8, 768, 2821, 64513], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": ["light.ledvance_rt_rgbw_77665544_level_light_color_on_off"], + "event_channels": [], + "manufacturer": "LEDVANCE", + "model": "RT RGBW", + }, + { + "endpoints": { + "1": { + "device_type": 81, + "endpoint_id": 1, + "in_clusters": [0, 1, 2, 3, 4, 5, 6, 10, 16, 2820], + "out_clusters": [10, 25], + "profile_id": 260, + }, + "100": { + "device_type": 263, + "endpoint_id": 100, + "in_clusters": [15], + "out_clusters": [4, 15], + "profile_id": 260, + }, + "2": { + "device_type": 9, + "endpoint_id": 2, + "in_clusters": [12], + "out_clusters": [4, 12], + "profile_id": 260, + }, + "3": { + "device_type": 83, + "endpoint_id": 3, + "in_clusters": [12], + "out_clusters": [12], + "profile_id": 260, + }, + }, + "entities": [ + "sensor.lumi_lumi_plug_maus01_77665544_electrical_measurement", + "sensor.lumi_lumi_plug_maus01_77665544_analog_input", + "sensor.lumi_lumi_plug_maus01_77665544_analog_input_2", + "sensor.lumi_lumi_plug_maus01_77665544_power", + "switch.lumi_lumi_plug_maus01_77665544_on_off", + ], + "event_channels": [], + "manufacturer": "LUMI", + "model": "lumi.plug.maus01", + }, + { + "endpoints": { + "1": { + "device_type": 257, + "endpoint_id": 1, + "in_clusters": [0, 1, 2, 3, 4, 5, 6, 10, 12, 16, 2820], + "out_clusters": [10, 25], + "profile_id": 260, + }, + "2": { + "device_type": 257, + "endpoint_id": 2, + "in_clusters": [4, 5, 6, 16], + "out_clusters": [], + "profile_id": 260, + }, + }, + "entities": [ + "sensor.lumi_lumi_relay_c2acn01_77665544_analog_input", + "sensor.lumi_lumi_relay_c2acn01_77665544_electrical_measurement", + "sensor.lumi_lumi_relay_c2acn01_77665544_power", + "light.lumi_lumi_relay_c2acn01_77665544_on_off", + "light.lumi_lumi_relay_c2acn01_77665544_on_off_2", + ], + "event_channels": [], + "manufacturer": "LUMI", + "model": "lumi.relay.c2acn01", + }, + { + "endpoints": { + "1": { + "device_type": 24321, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 18, 25, 65535], + "out_clusters": [0, 3, 4, 5, 18, 25, 65535], + "profile_id": 260, + }, + "2": { + "device_type": 24322, + "endpoint_id": 2, + "in_clusters": [3, 18], + "out_clusters": [3, 4, 5, 18], + "profile_id": 260, + }, + "3": { + "device_type": 24323, + "endpoint_id": 3, + "in_clusters": [3, 18], + "out_clusters": [3, 4, 5, 12, 18], + "profile_id": 260, + }, + }, + "entities": [ + "sensor.lumi_lumi_remote_b186acn01_77665544_multistate_input", + "sensor.lumi_lumi_remote_b186acn01_77665544_power", + "sensor.lumi_lumi_remote_b186acn01_77665544_multistate_input_2", + "sensor.lumi_lumi_remote_b186acn01_77665544_multistate_input_3", + ], + "event_channels": [], + "manufacturer": "LUMI", + "model": "lumi.remote.b186acn01", + }, + { + "endpoints": { + "1": { + "device_type": 24321, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 18, 25, 65535], + "out_clusters": [0, 3, 4, 5, 18, 25, 65535], + "profile_id": 260, + }, + "2": { + "device_type": 24322, + "endpoint_id": 2, + "in_clusters": [3, 18], + "out_clusters": [3, 4, 5, 18], + "profile_id": 260, + }, + "3": { + "device_type": 24323, + "endpoint_id": 3, + "in_clusters": [3, 18], + "out_clusters": [3, 4, 5, 12, 18], + "profile_id": 260, + }, + }, + "entities": [ + "sensor.lumi_lumi_remote_b286acn01_77665544_multistate_input", + "sensor.lumi_lumi_remote_b286acn01_77665544_power", + "sensor.lumi_lumi_remote_b286acn01_77665544_multistate_input_2", + "sensor.lumi_lumi_remote_b286acn01_77665544_multistate_input_3", + ], + "event_channels": [], + "manufacturer": "LUMI", + "model": "lumi.remote.b286acn01", + }, + { + "endpoints": { + "1": { + "device_type": 261, + "endpoint_id": 1, + "in_clusters": [0, 1, 3], + "out_clusters": [3, 6, 8, 768], + "profile_id": 260, + }, + "2": { + "device_type": -1, + "endpoint_id": 2, + "in_clusters": [], + "out_clusters": [], + "profile_id": -1, + }, + "3": { + "device_type": -1, + "endpoint_id": 3, + "in_clusters": [], + "out_clusters": [], + "profile_id": -1, + }, + "4": { + "device_type": -1, + "endpoint_id": 4, + "in_clusters": [], + "out_clusters": [], + "profile_id": -1, + }, + "5": { + "device_type": -1, + "endpoint_id": 5, + "in_clusters": [], + "out_clusters": [], + "profile_id": -1, + }, + "6": { + "device_type": -1, + "endpoint_id": 6, + "in_clusters": [], + "out_clusters": [], + "profile_id": -1, + }, + }, + "entities": ["sensor.lumi_lumi_remote_b286opcn01_77665544_power"], + "event_channels": [6, 8, 768], + "manufacturer": "LUMI", + "model": "lumi.remote.b286opcn01", + }, + { + "endpoints": { + "1": { + "device_type": 261, + "endpoint_id": 1, + "in_clusters": [0, 1, 3], + "out_clusters": [3, 6, 8, 768], + "profile_id": 260, + }, + "2": { + "device_type": 259, + "endpoint_id": 2, + "in_clusters": [3], + "out_clusters": [3, 6], + "profile_id": 260, + }, + "3": { + "device_type": -1, + "endpoint_id": 3, + "in_clusters": [], + "out_clusters": [], + "profile_id": -1, + }, + "4": { + "device_type": -1, + "endpoint_id": 4, + "in_clusters": [], + "out_clusters": [], + "profile_id": -1, + }, + "5": { + "device_type": -1, + "endpoint_id": 5, + "in_clusters": [], + "out_clusters": [], + "profile_id": -1, + }, + "6": { + "device_type": -1, + "endpoint_id": 6, + "in_clusters": [], + "out_clusters": [], + "profile_id": -1, + }, + }, + "entities": [ + "sensor.lumi_lumi_remote_b486opcn01_77665544_power", + "switch.lumi_lumi_remote_b486opcn01_77665544_on_off", + ], + "event_channels": [6, 8, 768, 6], + "manufacturer": "LUMI", + "model": "lumi.remote.b486opcn01", + }, + { + "endpoints": { + "1": { + "device_type": 261, + "endpoint_id": 1, + "in_clusters": [0, 1, 3], + "out_clusters": [3, 6, 8, 768], + "profile_id": 260, + }, + "2": { + "device_type": 259, + "endpoint_id": 2, + "in_clusters": [3], + "out_clusters": [3, 6], + "profile_id": 260, + }, + "3": { + "device_type": None, + "endpoint_id": 3, + "in_clusters": [], + "out_clusters": [], + "profile_id": None, + }, + "4": { + "device_type": None, + "endpoint_id": 4, + "in_clusters": [], + "out_clusters": [], + "profile_id": None, + }, + "5": { + "device_type": None, + "endpoint_id": 5, + "in_clusters": [], + "out_clusters": [], + "profile_id": None, + }, + "6": { + "device_type": None, + "endpoint_id": 6, + "in_clusters": [], + "out_clusters": [], + "profile_id": None, + }, + }, + "entities": [ + "sensor.lumi_lumi_remote_b686opcn01_77665544_power", + "switch.lumi_lumi_remote_b686opcn01_77665544_on_off", + ], + "event_channels": [6, 8, 768, 6], + "manufacturer": "LUMI", + "model": "lumi.remote.b686opcn01", + }, + { + "endpoints": { + "8": { + "device_type": 256, + "endpoint_id": 8, + "in_clusters": [0, 6, 11, 17], + "out_clusters": [0, 6], + "profile_id": 260, + } + }, + "entities": ["light.lumi_lumi_router_77665544_on_off_on_off"], + "event_channels": [6], + "manufacturer": "LUMI", + "model": "lumi.router", + }, + { + "endpoints": { + "1": { + "device_type": 28417, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 25], + "out_clusters": [0, 3, 4, 5, 18, 25], + "profile_id": 260, + }, + "2": { + "device_type": 28418, + "endpoint_id": 2, + "in_clusters": [3, 18], + "out_clusters": [3, 4, 5, 18], + "profile_id": 260, + }, + "3": { + "device_type": 28419, + "endpoint_id": 3, + "in_clusters": [3, 12], + "out_clusters": [3, 4, 5, 12], + "profile_id": 260, + }, + }, + "entities": [ + "sensor.lumi_lumi_sensor_cube_aqgl01_77665544_analog_input", + "sensor.lumi_lumi_sensor_cube_aqgl01_77665544_multistate_input", + "sensor.lumi_lumi_sensor_cube_aqgl01_77665544_power", + ], + "event_channels": [], + "manufacturer": "LUMI", + "model": "lumi.sensor_cube.aqgl01", + }, + { + "endpoints": { + "1": { + "device_type": 24322, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 25, 1026, 1029, 65535], + "out_clusters": [0, 3, 4, 5, 18, 25, 65535], + "profile_id": 260, + }, + "2": { + "device_type": 24322, + "endpoint_id": 2, + "in_clusters": [3], + "out_clusters": [3, 4, 5, 18], + "profile_id": 260, + }, + "3": { + "device_type": 24323, + "endpoint_id": 3, + "in_clusters": [3], + "out_clusters": [3, 4, 5, 12], + "profile_id": 260, + }, + }, + "entities": [ + "sensor.lumi_lumi_sensor_ht_77665544_power", + "sensor.lumi_lumi_sensor_ht_77665544_temperature", + "sensor.lumi_lumi_sensor_ht_77665544_humidity", + ], + "event_channels": [], + "manufacturer": "LUMI", + "model": "lumi.sensor_ht", + }, + { + "endpoints": { + "1": { + "device_type": 2128, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 25, 65535], + "out_clusters": [0, 3, 4, 5, 6, 8, 25], + "profile_id": 260, + } + }, + "entities": [ + "sensor.lumi_lumi_sensor_magnet_77665544_power", + "binary_sensor.lumi_lumi_sensor_magnet_77665544_on_off", + ], + "event_channels": [6, 8], + "manufacturer": "LUMI", + "model": "lumi.sensor_magnet", + }, + { + "endpoints": { + "1": { + "device_type": 24321, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 65535], + "out_clusters": [0, 4, 6, 65535], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.lumi_lumi_sensor_magnet_aq2_77665544_on_off", + "sensor.lumi_lumi_sensor_magnet_aq2_77665544_power", + ], + "event_channels": [6], + "manufacturer": "LUMI", + "model": "lumi.sensor_magnet.aq2", + }, + { + "endpoints": { + "1": { + "device_type": 263, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 1024, 1030, 1280, 65535], + "out_clusters": [0, 25], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.lumi_lumi_sensor_motion_aq2_77665544_occupancy", + "binary_sensor.lumi_lumi_sensor_motion_aq2_77665544_ias_zone", + "sensor.lumi_lumi_sensor_motion_aq2_77665544_illuminance", + "sensor.lumi_lumi_sensor_motion_aq2_77665544_power", + ], + "event_channels": [], + "manufacturer": "LUMI", + "model": "lumi.sensor_motion.aq2", + }, + { + "endpoints": { + "1": { + "device_type": 6, + "endpoint_id": 1, + "in_clusters": [0, 1, 3], + "out_clusters": [0, 4, 5, 6, 8, 25], + "profile_id": 260, + } + }, + "entities": ["sensor.lumi_lumi_sensor_switch_77665544_power"], + "event_channels": [6, 8], + "manufacturer": "LUMI", + "model": "lumi.sensor_switch", + }, + { + "endpoints": { + "1": { + "device_type": 6, + "endpoint_id": 1, + "in_clusters": [0, 1, 65535], + "out_clusters": [0, 4, 6, 65535], + "profile_id": 260, + } + }, + "entities": ["sensor.lumi_lumi_sensor_switch_aq2_77665544_power"], + "event_channels": [6], + "manufacturer": "LUMI", + "model": "lumi.sensor_switch.aq2", + }, + { + "endpoints": { + "1": { + "device_type": 6, + "endpoint_id": 1, + "in_clusters": [0, 1, 18], + "out_clusters": [0, 6], + "profile_id": 260, + } + }, + "entities": [ + "sensor.lumi_lumi_sensor_switch_aq3_77665544_multistate_input", + "sensor.lumi_lumi_sensor_switch_aq3_77665544_power", + ], + "event_channels": [6], + "manufacturer": "LUMI", + "model": "lumi.sensor_switch.aq3", + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 1280], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.lumi_lumi_sensor_wleak_aq1_77665544_ias_zone", + "sensor.lumi_lumi_sensor_wleak_aq1_77665544_power", + ], + "event_channels": [], + "manufacturer": "LUMI", + "model": "lumi.sensor_wleak.aq1", + }, + { + "endpoints": { + "1": { + "device_type": 10, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 25, 257, 1280], + "out_clusters": [0, 3, 4, 5, 25], + "profile_id": 260, + }, + "2": { + "device_type": 24322, + "endpoint_id": 2, + "in_clusters": [3], + "out_clusters": [3, 4, 5, 18], + "profile_id": 260, + }, + }, + "entities": [ + "binary_sensor.lumi_lumi_vibration_aq1_77665544_ias_zone", + "sensor.lumi_lumi_vibration_aq1_77665544_power", + "lock.lumi_lumi_vibration_aq1_77665544_door_lock", + ], + "event_channels": [], + "manufacturer": "LUMI", + "model": "lumi.vibration.aq1", + }, + { + "endpoints": { + "1": { + "device_type": 24321, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 1026, 1027, 1029, 65535], + "out_clusters": [0, 4, 65535], + "profile_id": 260, + } + }, + "entities": [ + "sensor.lumi_lumi_weather_77665544_temperature", + "sensor.lumi_lumi_weather_77665544_power", + "sensor.lumi_lumi_weather_77665544_humidity", + "sensor.lumi_lumi_weather_77665544_pressure", + ], + "event_channels": [], + "manufacturer": "LUMI", + "model": "lumi.weather", + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 32, 1280], + "out_clusters": [], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.nyce_3010_77665544_ias_zone", + "sensor.nyce_3010_77665544_power", + ], + "event_channels": [], + "manufacturer": "NYCE", + "model": "3010", + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 32, 1280], + "out_clusters": [], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.nyce_3014_77665544_ias_zone", + "sensor.nyce_3014_77665544_power", + ], + "event_channels": [], + "manufacturer": "NYCE", + "model": "3014", + }, + { + "endpoints": { + "3": { + "device_type": 258, + "endpoint_id": 3, + "in_clusters": [0, 3, 4, 5, 6, 8, 768, 64527], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": ["light.osram_lightify_a19_rgbw_77665544_level_light_color_on_off"], + "event_channels": [], + "manufacturer": "OSRAM", + "model": "LIGHTIFY A19 RGBW", + }, + { + "endpoints": { + "1": { + "device_type": 1, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 32, 2821], + "out_clusters": [3, 6, 8, 25], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.osram_lightify_dimming_switch_77665544_on_off", + "sensor.osram_lightify_dimming_switch_77665544_power", + ], + "event_channels": [6, 8], + "manufacturer": "OSRAM", + "model": "LIGHTIFY Dimming Switch", + }, + { + "endpoints": { + "3": { + "device_type": 258, + "endpoint_id": 3, + "in_clusters": [0, 3, 4, 5, 6, 8, 768, 64527], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": [ + "light.osram_lightify_flex_rgbw_77665544_level_light_color_on_off" + ], + "event_channels": [], + "manufacturer": "OSRAM", + "model": "LIGHTIFY Flex RGBW", + }, + { + "endpoints": { + "3": { + "device_type": 258, + "endpoint_id": 3, + "in_clusters": [0, 3, 4, 5, 6, 8, 768, 2820, 64527], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": [ + "sensor.osram_lightify_rt_tunable_white_77665544_electrical_measurement", + "light.osram_lightify_rt_tunable_white_77665544_level_light_color_on_off", + ], + "event_channels": [], + "manufacturer": "OSRAM", + "model": "LIGHTIFY RT Tunable White", + }, + { + "endpoints": { + "3": { + "device_type": 16, + "endpoint_id": 3, + "in_clusters": [0, 3, 4, 5, 6, 2820, 4096, 64527], + "out_clusters": [25], + "profile_id": 49246, + } + }, + "entities": [ + "sensor.osram_plug_01_77665544_electrical_measurement", + "switch.osram_plug_01_77665544_on_off", + ], + "event_channels": [], + "manufacturer": "OSRAM", + "model": "Plug 01", + }, + { + "endpoints": { + "1": { + "device_type": 2064, + "endpoint_id": 1, + "in_clusters": [0, 1, 32, 4096, 64768], + "out_clusters": [3, 4, 5, 6, 8, 25, 768, 4096], + "profile_id": 260, + }, + "2": { + "device_type": 2064, + "endpoint_id": 2, + "in_clusters": [0, 4096, 64768], + "out_clusters": [3, 4, 5, 6, 8, 768, 4096], + "profile_id": 260, + }, + "3": { + "device_type": 2064, + "endpoint_id": 3, + "in_clusters": [0, 4096, 64768], + "out_clusters": [3, 4, 5, 6, 8, 768, 4096], + "profile_id": 260, + }, + "4": { + "device_type": 2064, + "endpoint_id": 4, + "in_clusters": [0, 4096, 64768], + "out_clusters": [3, 4, 5, 6, 8, 768, 4096], + "profile_id": 260, + }, + "5": { + "device_type": 2064, + "endpoint_id": 5, + "in_clusters": [0, 4096, 64768], + "out_clusters": [3, 4, 5, 6, 8, 768, 4096], + "profile_id": 260, + }, + "6": { + "device_type": 2064, + "endpoint_id": 6, + "in_clusters": [0, 4096, 64768], + "out_clusters": [3, 4, 5, 6, 8, 768, 4096], + "profile_id": 260, + }, + }, + "entities": ["sensor.osram_switch_4x_lightify_77665544_power"], + "event_channels": [ + 6, + 8, + 768, + 6, + 8, + 768, + 6, + 8, + 768, + 6, + 8, + 768, + 6, + 8, + 768, + 6, + 8, + 768, + ], + "manufacturer": "OSRAM", + "model": "Switch 4x-LIGHTIFY", + }, + { + "endpoints": { + "1": { + "device_type": 2096, + "endpoint_id": 1, + "in_clusters": [0], + "out_clusters": [0, 3, 4, 5, 6, 8], + "profile_id": 49246, + }, + "2": { + "device_type": 12, + "endpoint_id": 2, + "in_clusters": [0, 1, 3, 15, 64512], + "out_clusters": [25], + "profile_id": 260, + }, + }, + "entities": ["sensor.philips_rwl020_77665544_power"], + "event_channels": [6, 8], + "manufacturer": "Philips", + "model": "RWL020", + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 32, 1026, 1280, 2821], + "out_clusters": [3, 25], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.samjin_button_77665544_ias_zone", + "sensor.samjin_button_77665544_temperature", + "sensor.samjin_button_77665544_power", + ], + "event_channels": [], + "manufacturer": "Samjin", + "model": "button", + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 32, 1026, 1280, 64514], + "out_clusters": [3, 25], + "profile_id": 260, + } + }, + "entities": [ + "sensor.samjin_multi_77665544_power", + "sensor.samjin_multi_77665544_temperature", + "binary_sensor.samjin_multi_77665544_ias_zone", + "binary_sensor.samjin_multi_77665544_manufacturer_specific", + ], + "event_channels": [], + "manufacturer": "Samjin", + "model": "multi", + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 32, 1026, 1280], + "out_clusters": [3, 25], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.samjin_water_77665544_ias_zone", + "sensor.samjin_water_77665544_power", + "sensor.samjin_water_77665544_temperature", + ], + "event_channels": [], + "manufacturer": "Samjin", + "model": "water", + }, + { + "endpoints": { + "1": { + "device_type": 0, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 4, 5, 6, 2820, 2821], + "out_clusters": [0, 1, 3, 4, 5, 6, 25, 2820, 2821], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.securifi_ltd_unk_model_77665544_on_off", + "sensor.securifi_ltd_unk_model_77665544_electrical_measurement", + "sensor.securifi_ltd_unk_model_77665544_power", + "switch.securifi_ltd_unk_model_77665544_on_off", + ], + "event_channels": [6], + "manufacturer": "Securifi Ltd.", + "model": None, + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 32, 1026, 1280, 2821], + "out_clusters": [3, 25], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.sercomm_corp_sz_dws04n_sf_77665544_ias_zone", + "sensor.sercomm_corp_sz_dws04n_sf_77665544_power", + "sensor.sercomm_corp_sz_dws04n_sf_77665544_temperature", + ], + "event_channels": [], + "manufacturer": "Sercomm Corp.", + "model": "SZ-DWS04N_SF", + }, + { + "endpoints": { + "1": { + "device_type": 256, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 4, 5, 6, 1794, 2820, 2821], + "out_clusters": [3, 10, 25, 2821], + "profile_id": 260, + }, + "2": { + "device_type": 259, + "endpoint_id": 2, + "in_clusters": [0, 1, 3], + "out_clusters": [3, 6], + "profile_id": 260, + }, + }, + "entities": [ + "sensor.sercomm_corp_sz_esw01_77665544_smartenergy_metering", + "sensor.sercomm_corp_sz_esw01_77665544_power", + "sensor.sercomm_corp_sz_esw01_77665544_power_2", + "sensor.sercomm_corp_sz_esw01_77665544_electrical_measurement", + "switch.sercomm_corp_sz_esw01_77665544_on_off", + "light.sercomm_corp_sz_esw01_77665544_on_off", + ], + "event_channels": [6], + "manufacturer": "Sercomm Corp.", + "model": "SZ-ESW01", + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 32, 1024, 1026, 1280, 2821], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.sercomm_corp_sz_pir04_77665544_ias_zone", + "sensor.sercomm_corp_sz_pir04_77665544_temperature", + "sensor.sercomm_corp_sz_pir04_77665544_illuminance", + "sensor.sercomm_corp_sz_pir04_77665544_power", + ], + "event_channels": [], + "manufacturer": "Sercomm Corp.", + "model": "SZ-PIR04", + }, + { + "endpoints": { + "1": { + "device_type": 2, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 2820, 2821, 65281], + "out_clusters": [3, 4, 25], + "profile_id": 260, + } + }, + "entities": [ + "sensor.sinope_technologies_rm3250zb_77665544_electrical_measurement", + "switch.sinope_technologies_rm3250zb_77665544_on_off", + ], + "event_channels": [], + "manufacturer": "Sinope Technologies", + "model": "RM3250ZB", + }, + { + "endpoints": { + "1": { + "device_type": 769, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 513, 516, 1026, 2820, 2821, 65281], + "out_clusters": [25, 65281], + "profile_id": 260, + }, + "196": { + "device_type": 769, + "endpoint_id": 196, + "in_clusters": [1], + "out_clusters": [], + "profile_id": 49757, + }, + }, + "entities": [ + "sensor.sinope_technologies_th1124zb_77665544_temperature", + "sensor.sinope_technologies_th1124zb_77665544_power", + "sensor.sinope_technologies_th1124zb_77665544_electrical_measurement", + ], + "event_channels": [], + "manufacturer": "Sinope Technologies", + "model": "TH1124ZB", + }, + { + "endpoints": { + "1": { + "device_type": 2, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 9, 15, 2820], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": [ + "sensor.smartthings_outletv4_77665544_electrical_measurement", + "switch.smartthings_outletv4_77665544_on_off", + ], + "event_channels": [], + "manufacturer": "SmartThings", + "model": "outletv4", + }, + { + "endpoints": { + "1": { + "device_type": 32768, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 15, 32], + "out_clusters": [3, 25], + "profile_id": 260, + } + }, + "entities": ["device_tracker.smartthings_tagv4_77665544_power"], + "event_channels": [], + "manufacturer": "SmartThings", + "model": "tagv4", + }, + { + "endpoints": { + "1": { + "device_type": 2, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 25], + "out_clusters": [], + "profile_id": 260, + } + }, + "entities": ["switch.third_reality_inc_3rss007z_77665544_on_off"], + "event_channels": [], + "manufacturer": "Third Reality, Inc", + "model": "3RSS007Z", + }, + { + "endpoints": { + "1": { + "device_type": 2, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 4, 5, 6, 25], + "out_clusters": [1], + "profile_id": 260, + } + }, + "entities": [ + "sensor.third_reality_inc_3rss008z_77665544_power", + "switch.third_reality_inc_3rss008z_77665544_on_off", + ], + "event_channels": [], + "manufacturer": "Third Reality, Inc", + "model": "3RSS008Z", + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 32, 1026, 1280, 2821], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.visonic_mct_340_e_77665544_ias_zone", + "sensor.visonic_mct_340_e_77665544_temperature", + "sensor.visonic_mct_340_e_77665544_power", + ], + "event_channels": [], + "manufacturer": "Visonic", + "model": "MCT-340 E", + }, + { + "endpoints": { + "1": { + "device_type": 1026, + "endpoint_id": 1, + "in_clusters": [0, 1, 3, 21, 32, 1280, 2821], + "out_clusters": [], + "profile_id": 260, + } + }, + "entities": [ + "binary_sensor.netvox_z308e3ed_77665544_ias_zone", + "sensor.netvox_z308e3ed_77665544_power", + ], + "event_channels": [], + "manufacturer": "netvox", + "model": "Z308E3ED", + }, + { + "endpoints": { + "1": { + "device_type": 257, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 8, 1794, 2821], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": [ + "light.sengled_e11_g13_77665544_level_on_off", + "sensor.sengled_e11_g13_77665544_smartenergy_metering", + ], + "event_channels": [], + "manufacturer": "sengled", + "model": "E11-G13", + }, + { + "endpoints": { + "1": { + "device_type": 257, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 8, 1794, 2821], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": [ + "sensor.sengled_e12_n14_77665544_smartenergy_metering", + "light.sengled_e12_n14_77665544_level_on_off", + ], + "event_channels": [], + "manufacturer": "sengled", + "model": "E12-N14", + }, + { + "endpoints": { + "1": { + "device_type": 257, + "endpoint_id": 1, + "in_clusters": [0, 3, 4, 5, 6, 8, 768, 1794, 2821], + "out_clusters": [25], + "profile_id": 260, + } + }, + "entities": [ + "sensor.sengled_z01_a19nae26_77665544_smartenergy_metering", + "light.sengled_z01_a19nae26_77665544_level_light_color_on_off", + ], + "event_channels": [], + "manufacturer": "sengled", + "model": "Z01-A19NAE26", + }, +]