Add power source to device and clean up zha listeners (#21174)
check available and add comments ensure order on API testpull/21238/head
parent
8b5aff63ae
commit
d1fa341a78
|
@ -62,7 +62,6 @@ ILLUMINANCE = 'illuminance'
|
|||
PRESSURE = 'pressure'
|
||||
METERING = 'metering'
|
||||
ELECTRICAL_MEASUREMENT = 'electrical_measurement'
|
||||
POWER_CONFIGURATION = 'power_configuration'
|
||||
GENERIC = 'generic'
|
||||
UNKNOWN = 'unknown'
|
||||
OPENING = 'opening'
|
||||
|
@ -73,6 +72,7 @@ ATTR_LEVEL = 'level'
|
|||
|
||||
LISTENER_ON_OFF = 'on_off'
|
||||
LISTENER_ATTRIBUTE = 'attribute'
|
||||
LISTENER_BASIC = 'basic'
|
||||
LISTENER_COLOR = 'color'
|
||||
LISTENER_FAN = 'fan'
|
||||
LISTENER_LEVEL = ATTR_LEVEL
|
||||
|
@ -113,6 +113,7 @@ CLUSTER_REPORT_CONFIGS = {}
|
|||
CUSTOM_CLUSTER_MAPPINGS = {}
|
||||
COMPONENT_CLUSTERS = {}
|
||||
EVENT_RELAY_CLUSTERS = []
|
||||
NO_SENSOR_CLUSTERS = []
|
||||
|
||||
REPORT_CONFIG_MAX_INT = 900
|
||||
REPORT_CONFIG_MAX_INT_BATTERY_SAVE = 10800
|
||||
|
|
|
@ -15,9 +15,9 @@ from .const import (
|
|||
ATTR_CLUSTER_ID, ATTR_ATTRIBUTE, ATTR_VALUE, ATTR_COMMAND, SERVER,
|
||||
ATTR_COMMAND_TYPE, ATTR_ARGS, CLIENT_COMMANDS, SERVER_COMMANDS,
|
||||
ATTR_ENDPOINT_ID, IEEE, MODEL, NAME, UNKNOWN, QUIRK_APPLIED,
|
||||
QUIRK_CLASS
|
||||
QUIRK_CLASS, LISTENER_BASIC
|
||||
)
|
||||
from .listeners import EventRelayListener
|
||||
from .listeners import EventRelayListener, BasicListener
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -59,6 +59,7 @@ class ZHADevice:
|
|||
self._zigpy_device.__class__.__module__,
|
||||
self._zigpy_device.__class__.__name__
|
||||
)
|
||||
self.power_source = None
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
|
@ -177,6 +178,13 @@ class ZHADevice:
|
|||
"""Initialize listeners."""
|
||||
_LOGGER.debug('%s: started initialization', self.name)
|
||||
await self._execute_listener_tasks('async_initialize', from_cache)
|
||||
self.power_source = self.cluster_listeners.get(
|
||||
LISTENER_BASIC).get_power_source()
|
||||
_LOGGER.debug(
|
||||
'%s: power source: %s',
|
||||
self.name,
|
||||
BasicListener.POWER_SOURCES.get(self.power_source)
|
||||
)
|
||||
_LOGGER.debug('%s: completed initialization', self.name)
|
||||
|
||||
async def _execute_listener_tasks(self, task_name, *args):
|
||||
|
|
|
@ -18,15 +18,15 @@ from .const import (
|
|||
ZHA_DISCOVERY_NEW, DEVICE_CLASS, SINGLE_INPUT_CLUSTER_DEVICE_CLASS,
|
||||
SINGLE_OUTPUT_CLUSTER_DEVICE_CLASS, COMPONENT_CLUSTERS, HUMIDITY,
|
||||
TEMPERATURE, ILLUMINANCE, PRESSURE, METERING, ELECTRICAL_MEASUREMENT,
|
||||
POWER_CONFIGURATION, GENERIC, SENSOR_TYPE, EVENT_RELAY_CLUSTERS,
|
||||
LISTENER_BATTERY, UNKNOWN, OPENING, ZONE, OCCUPANCY,
|
||||
CLUSTER_REPORT_CONFIGS, REPORT_CONFIG_IMMEDIATE, REPORT_CONFIG_ASAP,
|
||||
REPORT_CONFIG_DEFAULT, REPORT_CONFIG_MIN_INT, REPORT_CONFIG_MAX_INT,
|
||||
REPORT_CONFIG_OP, SIGNAL_REMOVE)
|
||||
GENERIC, SENSOR_TYPE, EVENT_RELAY_CLUSTERS, LISTENER_BATTERY, UNKNOWN,
|
||||
OPENING, ZONE, OCCUPANCY, CLUSTER_REPORT_CONFIGS, REPORT_CONFIG_IMMEDIATE,
|
||||
REPORT_CONFIG_ASAP, REPORT_CONFIG_DEFAULT, REPORT_CONFIG_MIN_INT,
|
||||
REPORT_CONFIG_MAX_INT, REPORT_CONFIG_OP, SIGNAL_REMOVE, NO_SENSOR_CLUSTERS)
|
||||
from .device import ZHADevice
|
||||
from ..device_entity import ZhaDeviceEntity
|
||||
from .listeners import (
|
||||
LISTENER_REGISTRY, AttributeListener, EventRelayListener, ZDOListener)
|
||||
LISTENER_REGISTRY, AttributeListener, EventRelayListener, ZDOListener,
|
||||
BasicListener)
|
||||
from .helpers import convert_ieee
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -165,7 +165,21 @@ class ZHAGateway:
|
|||
await self._component.async_add_entities([device_entity])
|
||||
|
||||
if is_new_join:
|
||||
# because it's a new join we can immediately mark the device as
|
||||
# available and we already loaded fresh state above
|
||||
zha_device.update_available(True)
|
||||
elif not zha_device.available and zha_device.power_source is not None\
|
||||
and zha_device.power_source != BasicListener.BATTERY:
|
||||
# the device is currently marked unavailable and it isn't a battery
|
||||
# powered device so we should be able to update it now
|
||||
_LOGGER.debug(
|
||||
"attempting to request fresh state for %s %s",
|
||||
zha_device.name,
|
||||
"with power source: {}".format(
|
||||
BasicListener.POWER_SOURCES.get(zha_device.power_source)
|
||||
)
|
||||
)
|
||||
await zha_device.async_initialize(from_cache=False)
|
||||
|
||||
async def _async_process_endpoint(
|
||||
self, endpoint_id, endpoint, discovery_infos, device, zha_device,
|
||||
|
@ -312,6 +326,13 @@ async def _handle_single_cluster_matches(hass, endpoint, zha_device,
|
|||
is_new_join,
|
||||
))
|
||||
|
||||
if cluster.cluster_id in NO_SENSOR_CLUSTERS:
|
||||
cluster_match_tasks.append(_handle_listener_only_cluster_match(
|
||||
zha_device,
|
||||
cluster,
|
||||
is_new_join,
|
||||
))
|
||||
|
||||
for cluster in endpoint.out_clusters.values():
|
||||
if cluster.cluster_id not in profile_clusters[1]:
|
||||
cluster_match_tasks.append(_handle_single_cluster_match(
|
||||
|
@ -338,6 +359,12 @@ async def _handle_single_cluster_matches(hass, endpoint, zha_device,
|
|||
return cluster_matches
|
||||
|
||||
|
||||
async def _handle_listener_only_cluster_match(
|
||||
zha_device, cluster, is_new_join):
|
||||
"""Handle a listener only cluster match."""
|
||||
await _create_cluster_listener(cluster, zha_device, is_new_join)
|
||||
|
||||
|
||||
async def _handle_single_cluster_match(hass, zha_device, cluster, device_key,
|
||||
device_classes, is_new_join):
|
||||
"""Dispatch a single cluster match to a HA component."""
|
||||
|
@ -352,11 +379,6 @@ async def _handle_single_cluster_match(hass, zha_device, cluster, device_key,
|
|||
listeners = []
|
||||
await _create_cluster_listener(cluster, zha_device, is_new_join,
|
||||
listeners=listeners)
|
||||
# don't actually create entities for PowerConfiguration
|
||||
# find a better way to do this without abusing single cluster reg
|
||||
from zigpy.zcl.clusters.general import PowerConfiguration
|
||||
if cluster.cluster_id == PowerConfiguration.cluster_id:
|
||||
return
|
||||
|
||||
cluster_key = "{}-{}".format(device_key, cluster.cluster_id)
|
||||
discovery_info = {
|
||||
|
@ -405,6 +427,10 @@ def establish_device_mappings():
|
|||
EVENT_RELAY_CLUSTERS.append(zcl.clusters.general.LevelControl.cluster_id)
|
||||
EVENT_RELAY_CLUSTERS.append(zcl.clusters.general.OnOff.cluster_id)
|
||||
|
||||
NO_SENSOR_CLUSTERS.append(zcl.clusters.general.Basic.cluster_id)
|
||||
NO_SENSOR_CLUSTERS.append(
|
||||
zcl.clusters.general.PowerConfiguration.cluster_id)
|
||||
|
||||
DEVICE_CLASS[zha.PROFILE_ID].update({
|
||||
zha.DeviceType.ON_OFF_SWITCH: 'binary_sensor',
|
||||
zha.DeviceType.LEVEL_CONTROL_SWITCH: 'binary_sensor',
|
||||
|
@ -442,7 +468,6 @@ def establish_device_mappings():
|
|||
zcl.clusters.measurement.IlluminanceMeasurement: 'sensor',
|
||||
zcl.clusters.smartenergy.Metering: 'sensor',
|
||||
zcl.clusters.homeautomation.ElectricalMeasurement: 'sensor',
|
||||
zcl.clusters.general.PowerConfiguration: 'sensor',
|
||||
zcl.clusters.security.IasZone: 'binary_sensor',
|
||||
zcl.clusters.measurement.OccupancySensing: 'binary_sensor',
|
||||
zcl.clusters.hvac.Fan: 'fan',
|
||||
|
@ -462,8 +487,6 @@ def establish_device_mappings():
|
|||
zcl.clusters.smartenergy.Metering.cluster_id: METERING,
|
||||
zcl.clusters.homeautomation.ElectricalMeasurement.cluster_id:
|
||||
ELECTRICAL_MEASUREMENT,
|
||||
zcl.clusters.general.PowerConfiguration.cluster_id:
|
||||
POWER_CONFIGURATION,
|
||||
})
|
||||
|
||||
BINARY_SENSOR_TYPES.update({
|
||||
|
@ -473,6 +496,19 @@ def establish_device_mappings():
|
|||
})
|
||||
|
||||
CLUSTER_REPORT_CONFIGS.update({
|
||||
zcl.clusters.general.Alarms.cluster_id: [],
|
||||
zcl.clusters.general.Basic.cluster_id: [],
|
||||
zcl.clusters.general.Commissioning.cluster_id: [],
|
||||
zcl.clusters.general.Identify.cluster_id: [],
|
||||
zcl.clusters.general.Groups.cluster_id: [],
|
||||
zcl.clusters.general.Scenes.cluster_id: [],
|
||||
zcl.clusters.general.Partition.cluster_id: [],
|
||||
zcl.clusters.general.Ota.cluster_id: [],
|
||||
zcl.clusters.general.PowerProfile.cluster_id: [],
|
||||
zcl.clusters.general.ApplianceControl.cluster_id: [],
|
||||
zcl.clusters.general.PollControl.cluster_id: [],
|
||||
zcl.clusters.general.GreenPowerProxy.cluster_id: [],
|
||||
zcl.clusters.general.OnOffConfiguration.cluster_id: [],
|
||||
zcl.clusters.general.OnOff.cluster_id: [{
|
||||
'attr': 'on_off',
|
||||
'config': REPORT_CONFIG_IMMEDIATE
|
||||
|
|
|
@ -18,7 +18,10 @@ from .helpers import (
|
|||
safe_read, get_attr_id_by_name, bind_cluster)
|
||||
from .const import (
|
||||
CLUSTER_REPORT_CONFIGS, REPORT_CONFIG_DEFAULT, SIGNAL_ATTR_UPDATED,
|
||||
SIGNAL_MOVE_LEVEL, SIGNAL_SET_LEVEL, SIGNAL_STATE_ATTR, ATTR_LEVEL
|
||||
SIGNAL_MOVE_LEVEL, SIGNAL_SET_LEVEL, SIGNAL_STATE_ATTR, LISTENER_BASIC,
|
||||
LISTENER_ATTRIBUTE, LISTENER_ON_OFF, LISTENER_COLOR, LISTENER_FAN,
|
||||
LISTENER_LEVEL, LISTENER_ZONE, LISTENER_ACTIVE_POWER, LISTENER_BATTERY,
|
||||
LISTENER_EVENT_RELAY
|
||||
)
|
||||
|
||||
LISTENER_REGISTRY = {}
|
||||
|
@ -30,12 +33,25 @@ def populate_listener_registry():
|
|||
"""Populate the listener registry."""
|
||||
from zigpy import zcl
|
||||
LISTENER_REGISTRY.update({
|
||||
zcl.clusters.general.Alarms.cluster_id: ClusterListener,
|
||||
zcl.clusters.general.Commissioning.cluster_id: ClusterListener,
|
||||
zcl.clusters.general.Identify.cluster_id: ClusterListener,
|
||||
zcl.clusters.general.Groups.cluster_id: ClusterListener,
|
||||
zcl.clusters.general.Scenes.cluster_id: ClusterListener,
|
||||
zcl.clusters.general.Partition.cluster_id: ClusterListener,
|
||||
zcl.clusters.general.Ota.cluster_id: ClusterListener,
|
||||
zcl.clusters.general.PowerProfile.cluster_id: ClusterListener,
|
||||
zcl.clusters.general.ApplianceControl.cluster_id: ClusterListener,
|
||||
zcl.clusters.general.PollControl.cluster_id: ClusterListener,
|
||||
zcl.clusters.general.GreenPowerProxy.cluster_id: ClusterListener,
|
||||
zcl.clusters.general.OnOffConfiguration.cluster_id: ClusterListener,
|
||||
zcl.clusters.general.OnOff.cluster_id: OnOffListener,
|
||||
zcl.clusters.general.LevelControl.cluster_id: LevelListener,
|
||||
zcl.clusters.lighting.Color.cluster_id: ColorListener,
|
||||
zcl.clusters.homeautomation.ElectricalMeasurement.cluster_id:
|
||||
ActivePowerListener,
|
||||
zcl.clusters.general.PowerConfiguration.cluster_id: BatteryListener,
|
||||
zcl.clusters.general.Basic.cluster_id: BasicListener,
|
||||
zcl.clusters.security.IasZone.cluster_id: IASZoneListener,
|
||||
zcl.clusters.hvac.Fan.cluster_id: FanListener,
|
||||
})
|
||||
|
@ -92,6 +108,7 @@ class ClusterListener:
|
|||
|
||||
def __init__(self, cluster, device):
|
||||
"""Initialize ClusterListener."""
|
||||
self.name = 'cluster_{}'.format(cluster.cluster_id)
|
||||
self._cluster = cluster
|
||||
self._zha_device = device
|
||||
self._unique_id = construct_unique_id(cluster)
|
||||
|
@ -216,11 +233,10 @@ class ClusterListener:
|
|||
class AttributeListener(ClusterListener):
|
||||
"""Listener for the attribute reports cluster."""
|
||||
|
||||
name = 'attribute'
|
||||
|
||||
def __init__(self, cluster, device):
|
||||
"""Initialize AttributeListener."""
|
||||
super().__init__(cluster, device)
|
||||
self.name = LISTENER_ATTRIBUTE
|
||||
attr = self._report_config[0].get('attr')
|
||||
if isinstance(attr, str):
|
||||
self._value_attribute = get_attr_id_by_name(self.cluster, attr)
|
||||
|
@ -247,13 +263,12 @@ class AttributeListener(ClusterListener):
|
|||
class OnOffListener(ClusterListener):
|
||||
"""Listener for the OnOff Zigbee cluster."""
|
||||
|
||||
name = 'on_off'
|
||||
|
||||
ON_OFF = 0
|
||||
|
||||
def __init__(self, cluster, device):
|
||||
"""Initialize ClusterListener."""
|
||||
"""Initialize OnOffListener."""
|
||||
super().__init__(cluster, device)
|
||||
self.name = LISTENER_ON_OFF
|
||||
self._state = None
|
||||
|
||||
@callback
|
||||
|
@ -295,10 +310,13 @@ class OnOffListener(ClusterListener):
|
|||
class LevelListener(ClusterListener):
|
||||
"""Listener for the LevelControl Zigbee cluster."""
|
||||
|
||||
name = ATTR_LEVEL
|
||||
|
||||
CURRENT_LEVEL = 0
|
||||
|
||||
def __init__(self, cluster, device):
|
||||
"""Initialize LevelListener."""
|
||||
super().__init__(cluster, device)
|
||||
self.name = LISTENER_LEVEL
|
||||
|
||||
@callback
|
||||
def cluster_command(self, tsn, command_id, args):
|
||||
"""Handle commands received to this cluster."""
|
||||
|
@ -350,7 +368,10 @@ class LevelListener(ClusterListener):
|
|||
class IASZoneListener(ClusterListener):
|
||||
"""Listener for the IASZone Zigbee cluster."""
|
||||
|
||||
name = 'zone'
|
||||
def __init__(self, cluster, device):
|
||||
"""Initialize LevelListener."""
|
||||
super().__init__(cluster, device)
|
||||
self.name = LISTENER_ZONE
|
||||
|
||||
@callback
|
||||
def cluster_command(self, tsn, command_id, args):
|
||||
|
@ -415,7 +436,10 @@ class IASZoneListener(ClusterListener):
|
|||
class ActivePowerListener(AttributeListener):
|
||||
"""Listener that polls active power level."""
|
||||
|
||||
name = 'active_power'
|
||||
def __init__(self, cluster, device):
|
||||
"""Initialize ActivePowerListener."""
|
||||
super().__init__(cluster, device)
|
||||
self.name = LISTENER_ACTIVE_POWER
|
||||
|
||||
async def async_update(self):
|
||||
"""Retrieve latest state."""
|
||||
|
@ -423,7 +447,7 @@ class ActivePowerListener(AttributeListener):
|
|||
|
||||
# This is a polling listener. Don't allow cache.
|
||||
result = await self.get_attribute_value(
|
||||
'active_power', from_cache=False)
|
||||
LISTENER_ACTIVE_POWER, from_cache=False)
|
||||
async_dispatcher_send(
|
||||
self._zha_device.hass,
|
||||
"{}_{}".format(self.unique_id, SIGNAL_ATTR_UPDATED),
|
||||
|
@ -433,14 +457,53 @@ class ActivePowerListener(AttributeListener):
|
|||
async def async_initialize(self, from_cache):
|
||||
"""Initialize listener."""
|
||||
await self.get_attribute_value(
|
||||
'active_power', from_cache=from_cache)
|
||||
LISTENER_ACTIVE_POWER, from_cache=from_cache)
|
||||
await super().async_initialize(from_cache)
|
||||
|
||||
|
||||
class BasicListener(ClusterListener):
|
||||
"""Listener to interact with the basic cluster."""
|
||||
|
||||
BATTERY = 3
|
||||
POWER_SOURCES = {
|
||||
0: 'Unknown',
|
||||
1: 'Mains (single phase)',
|
||||
2: 'Mains (3 phase)',
|
||||
BATTERY: 'Battery',
|
||||
4: 'DC source',
|
||||
5: 'Emergency mains constantly powered',
|
||||
6: 'Emergency mains and transfer switch'
|
||||
}
|
||||
|
||||
def __init__(self, cluster, device):
|
||||
"""Initialize BasicListener."""
|
||||
super().__init__(cluster, device)
|
||||
self.name = LISTENER_BASIC
|
||||
self._power_source = None
|
||||
|
||||
async def async_configure(self):
|
||||
"""Configure this listener."""
|
||||
await super().async_configure()
|
||||
await self.async_initialize(False)
|
||||
|
||||
async def async_initialize(self, from_cache):
|
||||
"""Initialize listener."""
|
||||
self._power_source = await self.get_attribute_value(
|
||||
'power_source', from_cache=from_cache)
|
||||
await super().async_initialize(from_cache)
|
||||
|
||||
def get_power_source(self):
|
||||
"""Get the power source."""
|
||||
return self._power_source
|
||||
|
||||
|
||||
class BatteryListener(ClusterListener):
|
||||
"""Listener that polls active power level."""
|
||||
|
||||
name = 'battery'
|
||||
def __init__(self, cluster, device):
|
||||
"""Initialize BatteryListener."""
|
||||
super().__init__(cluster, device)
|
||||
self.name = LISTENER_BATTERY
|
||||
|
||||
@callback
|
||||
def attribute_updated(self, attrid, value):
|
||||
|
@ -480,7 +543,10 @@ class BatteryListener(ClusterListener):
|
|||
class EventRelayListener(ClusterListener):
|
||||
"""Event relay that can be attached to zigbee clusters."""
|
||||
|
||||
name = 'event_relay'
|
||||
def __init__(self, cluster, device):
|
||||
"""Initialize EventRelayListener."""
|
||||
super().__init__(cluster, device)
|
||||
self.name = LISTENER_EVENT_RELAY
|
||||
|
||||
@callback
|
||||
def attribute_updated(self, attrid, value):
|
||||
|
@ -512,15 +578,14 @@ class EventRelayListener(ClusterListener):
|
|||
class ColorListener(ClusterListener):
|
||||
"""Color listener."""
|
||||
|
||||
name = 'color'
|
||||
|
||||
CAPABILITIES_COLOR_XY = 0x08
|
||||
CAPABILITIES_COLOR_TEMP = 0x10
|
||||
UNSUPPORTED_ATTRIBUTE = 0x86
|
||||
|
||||
def __init__(self, cluster, device):
|
||||
"""Initialize ClusterListener."""
|
||||
"""Initialize ColorListener."""
|
||||
super().__init__(cluster, device)
|
||||
self.name = LISTENER_COLOR
|
||||
self._color_capabilities = None
|
||||
|
||||
def get_color_capabilities(self):
|
||||
|
@ -550,10 +615,13 @@ class ColorListener(ClusterListener):
|
|||
class FanListener(ClusterListener):
|
||||
"""Fan listener."""
|
||||
|
||||
name = 'fan'
|
||||
|
||||
_value_attribute = 0
|
||||
|
||||
def __init__(self, cluster, device):
|
||||
"""Initialize FanListener."""
|
||||
super().__init__(cluster, device)
|
||||
self.name = LISTENER_FAN
|
||||
|
||||
async def async_set_speed(self, value) -> None:
|
||||
"""Set the speed of the fan."""
|
||||
from zigpy.exceptions import DeliveryError
|
||||
|
@ -595,10 +663,9 @@ class FanListener(ClusterListener):
|
|||
class ZDOListener:
|
||||
"""Listener for ZDO events."""
|
||||
|
||||
name = 'zdo'
|
||||
|
||||
def __init__(self, cluster, device):
|
||||
"""Initialize ClusterListener."""
|
||||
"""Initialize ZDOListener."""
|
||||
self.name = 'zdo'
|
||||
self._cluster = cluster
|
||||
self._zha_device = device
|
||||
self._status = ListenerStatus.CREATED
|
||||
|
|
|
@ -12,8 +12,8 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
|||
from .core.const import (
|
||||
DATA_ZHA, DATA_ZHA_DISPATCHERS, ZHA_DISCOVERY_NEW, HUMIDITY, TEMPERATURE,
|
||||
ILLUMINANCE, PRESSURE, METERING, ELECTRICAL_MEASUREMENT,
|
||||
POWER_CONFIGURATION, GENERIC, SENSOR_TYPE, LISTENER_ATTRIBUTE,
|
||||
LISTENER_ACTIVE_POWER, SIGNAL_ATTR_UPDATED, SIGNAL_STATE_ATTR)
|
||||
GENERIC, SENSOR_TYPE, LISTENER_ATTRIBUTE, LISTENER_ACTIVE_POWER,
|
||||
SIGNAL_ATTR_UPDATED, SIGNAL_STATE_ATTR)
|
||||
from .entity import ZhaEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
@ -71,7 +71,6 @@ UNIT_REGISTRY = {
|
|||
ILLUMINANCE: 'lx',
|
||||
METERING: 'W',
|
||||
ELECTRICAL_MEASUREMENT: 'W',
|
||||
POWER_CONFIGURATION: '%',
|
||||
GENERIC: None
|
||||
}
|
||||
|
||||
|
|
|
@ -174,6 +174,7 @@ async def async_test_device_join(
|
|||
only trigger during device joins can be tested.
|
||||
"""
|
||||
from zigpy.zcl.foundation import Status
|
||||
from zigpy.zcl.clusters.general import Basic
|
||||
# create zigpy device mocking out the zigbee network operations
|
||||
with patch(
|
||||
'zigpy.zcl.Cluster.configure_reporting',
|
||||
|
@ -182,7 +183,8 @@ async def async_test_device_join(
|
|||
'zigpy.zcl.Cluster.bind',
|
||||
return_value=mock_coro([Status.SUCCESS, Status.SUCCESS])):
|
||||
zigpy_device = await async_init_zigpy_device(
|
||||
hass, [cluster_id], [], device_type, zha_gateway,
|
||||
hass, [cluster_id, Basic.cluster_id], [], device_type,
|
||||
zha_gateway,
|
||||
ieee="00:0d:6f:00:0a:90:69:f7",
|
||||
manufacturer="FakeMan{}".format(cluster_id),
|
||||
model="FakeMod{}".format(cluster_id),
|
||||
|
|
|
@ -17,14 +17,14 @@ from .common import async_init_zigpy_device
|
|||
@pytest.fixture
|
||||
async def zha_client(hass, config_entry, zha_gateway, hass_ws_client):
|
||||
"""Test zha switch platform."""
|
||||
from zigpy.zcl.clusters.general import OnOff
|
||||
from zigpy.zcl.clusters.general import OnOff, Basic
|
||||
|
||||
# load the ZHA API
|
||||
async_load_api(hass, Mock(), zha_gateway)
|
||||
|
||||
# create zigpy device
|
||||
await async_init_zigpy_device(
|
||||
hass, [OnOff.cluster_id], [], None, zha_gateway)
|
||||
hass, [OnOff.cluster_id, Basic.cluster_id], [], None, zha_gateway)
|
||||
|
||||
# load up switch domain
|
||||
await hass.config_entries.async_forward_entry_setup(
|
||||
|
@ -44,10 +44,16 @@ async def test_device_clusters(hass, config_entry, zha_gateway, zha_client):
|
|||
|
||||
msg = await zha_client.receive_json()
|
||||
|
||||
assert len(msg['result']) == 1
|
||||
assert len(msg['result']) == 2
|
||||
|
||||
cluster_info = msg['result'][0]
|
||||
cluster_infos = sorted(msg['result'], key=lambda k: k[ID])
|
||||
|
||||
cluster_info = cluster_infos[0]
|
||||
assert cluster_info[TYPE] == IN
|
||||
assert cluster_info[ID] == 0
|
||||
assert cluster_info[NAME] == 'Basic'
|
||||
|
||||
cluster_info = cluster_infos[1]
|
||||
assert cluster_info[TYPE] == IN
|
||||
assert cluster_info[ID] == 6
|
||||
assert cluster_info[NAME] == 'OnOff'
|
||||
|
|
|
@ -11,13 +11,13 @@ async def test_binary_sensor(hass, config_entry, zha_gateway):
|
|||
"""Test zha binary_sensor platform."""
|
||||
from zigpy.zcl.clusters.security import IasZone
|
||||
from zigpy.zcl.clusters.measurement import OccupancySensing
|
||||
from zigpy.zcl.clusters.general import OnOff, LevelControl
|
||||
from zigpy.zcl.clusters.general import OnOff, LevelControl, Basic
|
||||
from zigpy.profiles.zha import DeviceType
|
||||
|
||||
# create zigpy devices
|
||||
zigpy_device_zone = await async_init_zigpy_device(
|
||||
hass,
|
||||
[IasZone.cluster_id],
|
||||
[IasZone.cluster_id, Basic.cluster_id],
|
||||
[],
|
||||
None,
|
||||
zha_gateway
|
||||
|
@ -25,7 +25,7 @@ async def test_binary_sensor(hass, config_entry, zha_gateway):
|
|||
|
||||
zigpy_device_remote = await async_init_zigpy_device(
|
||||
hass,
|
||||
[],
|
||||
[Basic.cluster_id],
|
||||
[OnOff.cluster_id, LevelControl.cluster_id],
|
||||
DeviceType.LEVEL_CONTROL_SWITCH,
|
||||
zha_gateway,
|
||||
|
@ -36,7 +36,7 @@ async def test_binary_sensor(hass, config_entry, zha_gateway):
|
|||
|
||||
zigpy_device_occupancy = await async_init_zigpy_device(
|
||||
hass,
|
||||
[OccupancySensing.cluster_id],
|
||||
[OccupancySensing.cluster_id, Basic.cluster_id],
|
||||
[],
|
||||
None,
|
||||
zha_gateway,
|
||||
|
|
|
@ -17,11 +17,12 @@ from .common import (
|
|||
async def test_fan(hass, config_entry, zha_gateway):
|
||||
"""Test zha fan platform."""
|
||||
from zigpy.zcl.clusters.hvac import Fan
|
||||
from zigpy.zcl.clusters.general import Basic
|
||||
from zigpy.zcl.foundation import Status
|
||||
|
||||
# create zigpy device
|
||||
zigpy_device = await async_init_zigpy_device(
|
||||
hass, [Fan.cluster_id], [], None, zha_gateway)
|
||||
hass, [Fan.cluster_id, Basic.cluster_id], [], None, zha_gateway)
|
||||
|
||||
# load up fan domain
|
||||
await hass.config_entries.async_forward_entry_setup(
|
||||
|
|
|
@ -14,13 +14,13 @@ OFF = 0
|
|||
|
||||
async def test_light(hass, config_entry, zha_gateway):
|
||||
"""Test zha light platform."""
|
||||
from zigpy.zcl.clusters.general import OnOff, LevelControl
|
||||
from zigpy.zcl.clusters.general import OnOff, LevelControl, Basic
|
||||
from zigpy.profiles.zha import DeviceType
|
||||
|
||||
# create zigpy devices
|
||||
zigpy_device_on_off = await async_init_zigpy_device(
|
||||
hass,
|
||||
[OnOff.cluster_id],
|
||||
[OnOff.cluster_id, Basic.cluster_id],
|
||||
[],
|
||||
DeviceType.ON_OFF_LIGHT,
|
||||
zha_gateway
|
||||
|
@ -28,7 +28,7 @@ async def test_light(hass, config_entry, zha_gateway):
|
|||
|
||||
zigpy_device_level = await async_init_zigpy_device(
|
||||
hass,
|
||||
[OnOff.cluster_id, LevelControl.cluster_id],
|
||||
[OnOff.cluster_id, LevelControl.cluster_id, Basic.cluster_id],
|
||||
[],
|
||||
DeviceType.ON_OFF_LIGHT,
|
||||
zha_gateway,
|
||||
|
|
|
@ -86,6 +86,7 @@ async def async_build_devices(hass, zha_gateway, config_entry, cluster_ids):
|
|||
A dict containing relevant device info for testing is returned. It contains
|
||||
the entity id, zigpy device, and the zigbee cluster for the sensor.
|
||||
"""
|
||||
from zigpy.zcl.clusters.general import Basic
|
||||
device_infos = {}
|
||||
counter = 0
|
||||
for cluster_id in cluster_ids:
|
||||
|
@ -93,7 +94,7 @@ async def async_build_devices(hass, zha_gateway, config_entry, cluster_ids):
|
|||
device_infos[cluster_id] = {"zigpy_device": None}
|
||||
device_infos[cluster_id]["zigpy_device"] = await \
|
||||
async_init_zigpy_device(
|
||||
hass, [cluster_id], [], None, zha_gateway,
|
||||
hass, [cluster_id, Basic.cluster_id], [], None, zha_gateway,
|
||||
ieee="{}0:15:8d:00:02:32:4f:32".format(counter),
|
||||
manufacturer="Fake{}".format(cluster_id),
|
||||
model="FakeModel{}".format(cluster_id))
|
||||
|
|
|
@ -14,12 +14,12 @@ OFF = 0
|
|||
|
||||
async def test_switch(hass, config_entry, zha_gateway):
|
||||
"""Test zha switch platform."""
|
||||
from zigpy.zcl.clusters.general import OnOff
|
||||
from zigpy.zcl.clusters.general import OnOff, Basic
|
||||
from zigpy.zcl.foundation import Status
|
||||
|
||||
# create zigpy device
|
||||
zigpy_device = await async_init_zigpy_device(
|
||||
hass, [OnOff.cluster_id], [], None, zha_gateway)
|
||||
hass, [OnOff.cluster_id, Basic.cluster_id], [], None, zha_gateway)
|
||||
|
||||
# load up switch domain
|
||||
await hass.config_entries.async_forward_entry_setup(
|
||||
|
|
Loading…
Reference in New Issue