Remove ZHA attribute listening channel ()

* remove AttributeListeningChannel
* pull sleeps
* update signature to fix pylint
This commit is contained in:
Alexei Chetroi 2020-03-04 13:11:53 -05:00 committed by GitHub
parent 7f91501a36
commit 20333703c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
21 changed files with 124 additions and 108 deletions

View file

@ -103,9 +103,9 @@ class BinarySensor(ZhaEntity, BinarySensorDevice):
return self._device_class return self._device_class
@callback @callback
def async_set_state(self, state): def async_set_state(self, attr_id, attr_name, value):
"""Set the state.""" """Set the state."""
self._state = bool(state) self._state = bool(value)
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()
async def async_update(self): async def async_update(self):

View file

@ -235,7 +235,7 @@ class ChannelPool:
"""Create and add channels for all input clusters.""" """Create and add channels for all input clusters."""
for cluster_id, cluster in self.endpoint.in_clusters.items(): for cluster_id, cluster in self.endpoint.in_clusters.items():
channel_class = zha_regs.ZIGBEE_CHANNEL_REGISTRY.get( channel_class = zha_regs.ZIGBEE_CHANNEL_REGISTRY.get(
cluster_id, base.AttributeListeningChannel cluster_id, base.ZigbeeChannel
) )
# really ugly hack to deal with xiaomi using the door lock cluster # really ugly hack to deal with xiaomi using the door lock cluster
# incorrectly. # incorrectly.
@ -243,7 +243,7 @@ class ChannelPool:
hasattr(cluster, "ep_attribute") hasattr(cluster, "ep_attribute")
and cluster.ep_attribute == "multistate_input" and cluster.ep_attribute == "multistate_input"
): ):
channel_class = base.AttributeListeningChannel channel_class = base.ZigbeeChannel
# end of ugly hack # end of ugly hack
channel = channel_class(cluster, self) channel = channel_class(cluster, self)
if channel.name == const.CHANNEL_POWER_CONFIGURATION: if channel.name == const.CHANNEL_POWER_CONFIGURATION:

View file

@ -4,7 +4,6 @@ import asyncio
from enum import Enum from enum import Enum
from functools import wraps from functools import wraps
import logging import logging
from random import uniform
from typing import Any, Union from typing import Any, Union
import zigpy.exceptions import zigpy.exceptions
@ -22,7 +21,6 @@ from ..const import (
ATTR_VALUE, ATTR_VALUE,
CHANNEL_EVENT_RELAY, CHANNEL_EVENT_RELAY,
CHANNEL_ZDO, CHANNEL_ZDO,
REPORT_CONFIG_DEFAULT,
REPORT_CONFIG_MAX_INT, REPORT_CONFIG_MAX_INT,
REPORT_CONFIG_MIN_INT, REPORT_CONFIG_MIN_INT,
REPORT_CONFIG_RPT_CHANGE, REPORT_CONFIG_RPT_CHANGE,
@ -84,7 +82,7 @@ class ZigbeeChannel(LogMixin):
REPORT_CONFIG = () REPORT_CONFIG = ()
def __init__( def __init__(
self, cluster: zha_typing.ZigpyClusterType, ch_pool: zha_typing.ChannelPoolType, self, cluster: zha_typing.ZigpyClusterType, ch_pool: zha_typing.ChannelPoolType
) -> None: ) -> None:
"""Initialize ZigbeeChannel.""" """Initialize ZigbeeChannel."""
self._channel_name = cluster.ep_attribute self._channel_name = cluster.ep_attribute
@ -97,6 +95,12 @@ class ZigbeeChannel(LogMixin):
unique_id = ch_pool.unique_id.replace("-", ":") unique_id = ch_pool.unique_id.replace("-", ":")
self._unique_id = f"{unique_id}:0x{cluster.cluster_id:04x}" self._unique_id = f"{unique_id}:0x{cluster.cluster_id:04x}"
self._report_config = self.REPORT_CONFIG self._report_config = self.REPORT_CONFIG
if not hasattr(self, "_value_attribute") and len(self._report_config) > 0:
attr = self._report_config[0].get("attr")
if isinstance(attr, str):
self.value_attribute = get_attr_id_by_name(self.cluster, attr)
else:
self.value_attribute = attr
self._status = ChannelStatus.CREATED self._status = ChannelStatus.CREATED
self._cluster.add_listener(self) self._cluster.add_listener(self)
@ -200,7 +204,6 @@ class ZigbeeChannel(LogMixin):
await self.configure_reporting( await self.configure_reporting(
report_config["attr"], report_config["config"] report_config["attr"], report_config["config"]
) )
await asyncio.sleep(uniform(0.1, 0.5))
self.debug("finished channel configuration") self.debug("finished channel configuration")
else: else:
self.debug("skipping channel configuration") self.debug("skipping channel configuration")
@ -209,6 +212,8 @@ class ZigbeeChannel(LogMixin):
async def async_initialize(self, from_cache): async def async_initialize(self, from_cache):
"""Initialize channel.""" """Initialize channel."""
self.debug("initializing channel: from_cache: %s", from_cache) self.debug("initializing channel: from_cache: %s", from_cache)
for report_config in self._report_config:
await self.get_attribute_value(report_config["attr"], from_cache=from_cache)
self._status = ChannelStatus.INITIALIZED self._status = ChannelStatus.INITIALIZED
@callback @callback
@ -219,7 +224,12 @@ class ZigbeeChannel(LogMixin):
@callback @callback
def attribute_updated(self, attrid, value): def attribute_updated(self, attrid, value):
"""Handle attribute updates on this cluster.""" """Handle attribute updates on this cluster."""
pass self.async_send_signal(
f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}",
attrid,
self.cluster.attributes.get(attrid, [attrid])[0],
value,
)
@callback @callback
def zdo_command(self, *args, **kwargs): def zdo_command(self, *args, **kwargs):
@ -272,36 +282,6 @@ class ZigbeeChannel(LogMixin):
return self.__getattribute__(name) return self.__getattribute__(name)
class AttributeListeningChannel(ZigbeeChannel):
"""Channel for attribute reports from the cluster."""
REPORT_CONFIG = [{"attr": 0, "config": REPORT_CONFIG_DEFAULT}]
def __init__(
self, cluster: zha_typing.ZigpyClusterType, ch_pool: zha_typing.ChannelPoolType,
) -> None:
"""Initialize AttributeListeningChannel."""
super().__init__(cluster, ch_pool)
attr = self._report_config[0].get("attr")
if isinstance(attr, str):
self.value_attribute = get_attr_id_by_name(self.cluster, attr)
else:
self.value_attribute = attr
@callback
def attribute_updated(self, attrid, value):
"""Handle attribute updates on this cluster."""
if attrid == self.value_attribute:
self.async_send_signal(f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", value)
async def async_initialize(self, from_cache):
"""Initialize listener."""
await self.get_attribute_value(
self._report_config[0].get("attr"), from_cache=from_cache
)
await super().async_initialize(from_cache)
class ZDOChannel(LogMixin): class ZDOChannel(LogMixin):
"""Channel for ZDO events.""" """Channel for ZDO events."""

View file

@ -23,7 +23,9 @@ class DoorLockChannel(ZigbeeChannel):
"""Retrieve latest state.""" """Retrieve latest state."""
result = await self.get_attribute_value("lock_state", from_cache=True) result = await self.get_attribute_value("lock_state", from_cache=True)
self.async_send_signal(f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", result) self.async_send_signal(
f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", 0, "lock_state", result
)
@callback @callback
def attribute_updated(self, attrid, value): def attribute_updated(self, attrid, value):
@ -33,7 +35,9 @@ class DoorLockChannel(ZigbeeChannel):
"Attribute report '%s'[%s] = %s", self.cluster.name, attr_name, value "Attribute report '%s'[%s] = %s", self.cluster.name, attr_name, value
) )
if attrid == self._value_attribute: if attrid == self._value_attribute:
self.async_send_signal(f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", value) self.async_send_signal(
f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", attrid, attr_name, value
)
async def async_initialize(self, from_cache): async def async_initialize(self, from_cache):
"""Initialize channel.""" """Initialize channel."""
@ -63,8 +67,12 @@ class WindowCovering(ZigbeeChannel):
"current_position_lift_percentage", from_cache=False "current_position_lift_percentage", from_cache=False
) )
self.debug("read current position: %s", result) self.debug("read current position: %s", result)
self.async_send_signal(
self.async_send_signal(f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", result) f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}",
8,
"current_position_lift_percentage",
result,
)
@callback @callback
def attribute_updated(self, attrid, value): def attribute_updated(self, attrid, value):
@ -74,7 +82,9 @@ class WindowCovering(ZigbeeChannel):
"Attribute report '%s'[%s] = %s", self.cluster.name, attr_name, value "Attribute report '%s'[%s] = %s", self.cluster.name, attr_name, value
) )
if attrid == self._value_attribute: if attrid == self._value_attribute:
self.async_send_signal(f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", value) self.async_send_signal(
f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", attrid, attr_name, value
)
async def async_initialize(self, from_cache): async def async_initialize(self, from_cache):
"""Initialize channel.""" """Initialize channel."""

View file

@ -18,7 +18,7 @@ from ..const import (
SIGNAL_STATE_ATTR, SIGNAL_STATE_ATTR,
) )
from ..helpers import get_attr_id_by_name from ..helpers import get_attr_id_by_name
from .base import AttributeListeningChannel, ZigbeeChannel, parse_and_log_command from .base import ZigbeeChannel, parse_and_log_command
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -31,21 +31,21 @@ class Alarms(ZigbeeChannel):
@registries.ZIGBEE_CHANNEL_REGISTRY.register(general.AnalogInput.cluster_id) @registries.ZIGBEE_CHANNEL_REGISTRY.register(general.AnalogInput.cluster_id)
class AnalogInput(AttributeListeningChannel): class AnalogInput(ZigbeeChannel):
"""Analog Input channel.""" """Analog Input channel."""
REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}] REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}]
@registries.ZIGBEE_CHANNEL_REGISTRY.register(general.AnalogOutput.cluster_id) @registries.ZIGBEE_CHANNEL_REGISTRY.register(general.AnalogOutput.cluster_id)
class AnalogOutput(AttributeListeningChannel): class AnalogOutput(ZigbeeChannel):
"""Analog Output channel.""" """Analog Output channel."""
REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}] REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}]
@registries.ZIGBEE_CHANNEL_REGISTRY.register(general.AnalogValue.cluster_id) @registries.ZIGBEE_CHANNEL_REGISTRY.register(general.AnalogValue.cluster_id)
class AnalogValue(AttributeListeningChannel): class AnalogValue(ZigbeeChannel):
"""Analog Value channel.""" """Analog Value channel."""
REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}] REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}]
@ -77,7 +77,7 @@ class BasicChannel(ZigbeeChannel):
} }
def __init__( def __init__(
self, cluster: zha_typing.ZigpyClusterType, ch_pool: zha_typing.ChannelPoolType, self, cluster: zha_typing.ZigpyClusterType, ch_pool: zha_typing.ChannelPoolType
) -> None: ) -> None:
"""Initialize BasicChannel.""" """Initialize BasicChannel."""
super().__init__(cluster, ch_pool) super().__init__(cluster, ch_pool)
@ -101,21 +101,21 @@ class BasicChannel(ZigbeeChannel):
@registries.ZIGBEE_CHANNEL_REGISTRY.register(general.BinaryInput.cluster_id) @registries.ZIGBEE_CHANNEL_REGISTRY.register(general.BinaryInput.cluster_id)
class BinaryInput(AttributeListeningChannel): class BinaryInput(ZigbeeChannel):
"""Binary Input channel.""" """Binary Input channel."""
REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}] REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}]
@registries.ZIGBEE_CHANNEL_REGISTRY.register(general.BinaryOutput.cluster_id) @registries.ZIGBEE_CHANNEL_REGISTRY.register(general.BinaryOutput.cluster_id)
class BinaryOutput(AttributeListeningChannel): class BinaryOutput(ZigbeeChannel):
"""Binary Output channel.""" """Binary Output channel."""
REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}] REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}]
@registries.ZIGBEE_CHANNEL_REGISTRY.register(general.BinaryValue.cluster_id) @registries.ZIGBEE_CHANNEL_REGISTRY.register(general.BinaryValue.cluster_id)
class BinaryValue(AttributeListeningChannel): class BinaryValue(ZigbeeChannel):
"""Binary Value channel.""" """Binary Value channel."""
REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}] REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}]
@ -209,21 +209,21 @@ class LevelControlChannel(ZigbeeChannel):
@registries.ZIGBEE_CHANNEL_REGISTRY.register(general.MultistateInput.cluster_id) @registries.ZIGBEE_CHANNEL_REGISTRY.register(general.MultistateInput.cluster_id)
class MultistateInput(AttributeListeningChannel): class MultistateInput(ZigbeeChannel):
"""Multistate Input channel.""" """Multistate Input channel."""
REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}] REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}]
@registries.ZIGBEE_CHANNEL_REGISTRY.register(general.MultistateOutput.cluster_id) @registries.ZIGBEE_CHANNEL_REGISTRY.register(general.MultistateOutput.cluster_id)
class MultistateOutput(AttributeListeningChannel): class MultistateOutput(ZigbeeChannel):
"""Multistate Output channel.""" """Multistate Output channel."""
REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}] REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}]
@registries.ZIGBEE_CHANNEL_REGISTRY.register(general.MultistateValue.cluster_id) @registries.ZIGBEE_CHANNEL_REGISTRY.register(general.MultistateValue.cluster_id)
class MultistateValue(AttributeListeningChannel): class MultistateValue(ZigbeeChannel):
"""Multistate Value channel.""" """Multistate Value channel."""
REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}] REPORT_CONFIG = [{"attr": "present_value", "config": REPORT_CONFIG_DEFAULT}]
@ -242,7 +242,7 @@ class OnOffChannel(ZigbeeChannel):
REPORT_CONFIG = ({"attr": "on_off", "config": REPORT_CONFIG_IMMEDIATE},) REPORT_CONFIG = ({"attr": "on_off", "config": REPORT_CONFIG_IMMEDIATE},)
def __init__( def __init__(
self, cluster: zha_typing.ZigpyClusterType, ch_pool: zha_typing.ChannelPoolType, self, cluster: zha_typing.ZigpyClusterType, ch_pool: zha_typing.ChannelPoolType
) -> None: ) -> None:
"""Initialize OnOffChannel.""" """Initialize OnOffChannel."""
super().__init__(cluster, ch_pool) super().__init__(cluster, ch_pool)
@ -286,7 +286,9 @@ class OnOffChannel(ZigbeeChannel):
def attribute_updated(self, attrid, value): def attribute_updated(self, attrid, value):
"""Handle attribute updates on this cluster.""" """Handle attribute updates on this cluster."""
if attrid == self.ON_OFF: if attrid == self.ON_OFF:
self.async_send_signal(f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", value) self.async_send_signal(
f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", attrid, "on_off", value
)
self._state = bool(value) self._state = bool(value)
async def async_initialize(self, from_cache): async def async_initialize(self, from_cache):
@ -354,7 +356,12 @@ class PowerConfigurationChannel(ZigbeeChannel):
else: else:
attr_id = attr attr_id = attr
if attrid == attr_id: if attrid == attr_id:
self.async_send_signal(f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", value) self.async_send_signal(
f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}",
attrid,
self.cluster.attributes.get(attrid, [attrid])[0],
value,
)
return return
attr_name = self.cluster.attributes.get(attrid, [attrid])[0] attr_name = self.cluster.attributes.get(attrid, [attrid])[0]
self.async_send_signal( self.async_send_signal(

View file

@ -10,7 +10,7 @@ from ..const import (
REPORT_CONFIG_DEFAULT, REPORT_CONFIG_DEFAULT,
SIGNAL_ATTR_UPDATED, SIGNAL_ATTR_UPDATED,
) )
from .base import AttributeListeningChannel, ZigbeeChannel from .base import ZigbeeChannel
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -52,7 +52,7 @@ class Diagnostic(ZigbeeChannel):
@registries.ZIGBEE_CHANNEL_REGISTRY.register( @registries.ZIGBEE_CHANNEL_REGISTRY.register(
homeautomation.ElectricalMeasurement.cluster_id homeautomation.ElectricalMeasurement.cluster_id
) )
class ElectricalMeasurementChannel(AttributeListeningChannel): class ElectricalMeasurementChannel(ZigbeeChannel):
"""Channel that polls active power level.""" """Channel that polls active power level."""
CHANNEL_NAME = CHANNEL_ELECTRICAL_MEASUREMENT CHANNEL_NAME = CHANNEL_ELECTRICAL_MEASUREMENT
@ -60,7 +60,7 @@ class ElectricalMeasurementChannel(AttributeListeningChannel):
REPORT_CONFIG = ({"attr": "active_power", "config": REPORT_CONFIG_DEFAULT},) REPORT_CONFIG = ({"attr": "active_power", "config": REPORT_CONFIG_DEFAULT},)
def __init__( def __init__(
self, cluster: zha_typing.ZigpyClusterType, ch_pool: zha_typing.ChannelPoolType, self, cluster: zha_typing.ZigpyClusterType, ch_pool: zha_typing.ChannelPoolType
) -> None: ) -> None:
"""Initialize Metering.""" """Initialize Metering."""
super().__init__(cluster, ch_pool) super().__init__(cluster, ch_pool)
@ -73,7 +73,9 @@ class ElectricalMeasurementChannel(AttributeListeningChannel):
# This is a polling channel. Don't allow cache. # This is a polling channel. Don't allow cache.
result = await self.get_attribute_value("active_power", from_cache=False) result = await self.get_attribute_value("active_power", from_cache=False)
self.async_send_signal(f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", result) self.async_send_signal(
f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", 0x050B, "active_power", result
)
async def async_initialize(self, from_cache): async def async_initialize(self, from_cache):
"""Initialize channel.""" """Initialize channel."""

View file

@ -40,8 +40,9 @@ class FanChannel(ZigbeeChannel):
async def async_update(self): async def async_update(self):
"""Retrieve latest state.""" """Retrieve latest state."""
result = await self.get_attribute_value("fan_mode", from_cache=True) result = await self.get_attribute_value("fan_mode", from_cache=True)
self.async_send_signal(
self.async_send_signal(f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", result) f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", 0, "fan_mode", result
)
@callback @callback
def attribute_updated(self, attrid, value): def attribute_updated(self, attrid, value):
@ -51,7 +52,9 @@ class FanChannel(ZigbeeChannel):
"Attribute report '%s'[%s] = %s", self.cluster.name, attr_name, value "Attribute report '%s'[%s] = %s", self.cluster.name, attr_name, value
) )
if attrid == self._value_attribute: if attrid == self._value_attribute:
self.async_send_signal(f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", value) self.async_send_signal(
f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", attrid, attr_name, value
)
async def async_initialize(self, from_cache): async def async_initialize(self, from_cache):
"""Initialize channel.""" """Initialize channel."""

View file

@ -14,13 +14,13 @@ from ..const import (
SIGNAL_ATTR_UPDATED, SIGNAL_ATTR_UPDATED,
UNKNOWN, UNKNOWN,
) )
from .base import AttributeListeningChannel, ZigbeeChannel from .base import ZigbeeChannel
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@registries.ZIGBEE_CHANNEL_REGISTRY.register(registries.SMARTTHINGS_HUMIDITY_CLUSTER) @registries.ZIGBEE_CHANNEL_REGISTRY.register(registries.SMARTTHINGS_HUMIDITY_CLUSTER)
class SmartThingsHumidity(AttributeListeningChannel): class SmartThingsHumidity(ZigbeeChannel):
"""Smart Things Humidity channel.""" """Smart Things Humidity channel."""
REPORT_CONFIG = [ REPORT_CONFIG = [
@ -50,7 +50,7 @@ class OppleRemote(ZigbeeChannel):
@registries.ZIGBEE_CHANNEL_REGISTRY.register( @registries.ZIGBEE_CHANNEL_REGISTRY.register(
registries.SMARTTHINGS_ACCELERATION_CLUSTER registries.SMARTTHINGS_ACCELERATION_CLUSTER
) )
class SmartThingsAcceleration(AttributeListeningChannel): class SmartThingsAcceleration(ZigbeeChannel):
"""Smart Things Acceleration channel.""" """Smart Things Acceleration channel."""
REPORT_CONFIG = [ REPORT_CONFIG = [
@ -64,7 +64,12 @@ class SmartThingsAcceleration(AttributeListeningChannel):
def attribute_updated(self, attrid, value): def attribute_updated(self, attrid, value):
"""Handle attribute updates on this cluster.""" """Handle attribute updates on this cluster."""
if attrid == self.value_attribute: if attrid == self.value_attribute:
self.async_send_signal(f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", value) self.async_send_signal(
f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}",
attrid,
self._cluster.attributes.get(attrid, [UNKNOWN])[0],
value,
)
return return
self.zha_send_event( self.zha_send_event(

View file

@ -10,13 +10,13 @@ from ..const import (
REPORT_CONFIG_MAX_INT, REPORT_CONFIG_MAX_INT,
REPORT_CONFIG_MIN_INT, REPORT_CONFIG_MIN_INT,
) )
from .base import AttributeListeningChannel from .base import ZigbeeChannel
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@registries.ZIGBEE_CHANNEL_REGISTRY.register(measurement.FlowMeasurement.cluster_id) @registries.ZIGBEE_CHANNEL_REGISTRY.register(measurement.FlowMeasurement.cluster_id)
class FlowMeasurement(AttributeListeningChannel): class FlowMeasurement(ZigbeeChannel):
"""Flow Measurement channel.""" """Flow Measurement channel."""
REPORT_CONFIG = [{"attr": "measured_value", "config": REPORT_CONFIG_DEFAULT}] REPORT_CONFIG = [{"attr": "measured_value", "config": REPORT_CONFIG_DEFAULT}]
@ -25,7 +25,7 @@ class FlowMeasurement(AttributeListeningChannel):
@registries.ZIGBEE_CHANNEL_REGISTRY.register( @registries.ZIGBEE_CHANNEL_REGISTRY.register(
measurement.IlluminanceLevelSensing.cluster_id measurement.IlluminanceLevelSensing.cluster_id
) )
class IlluminanceLevelSensing(AttributeListeningChannel): class IlluminanceLevelSensing(ZigbeeChannel):
"""Illuminance Level Sensing channel.""" """Illuminance Level Sensing channel."""
REPORT_CONFIG = [{"attr": "level_status", "config": REPORT_CONFIG_DEFAULT}] REPORT_CONFIG = [{"attr": "level_status", "config": REPORT_CONFIG_DEFAULT}]
@ -34,7 +34,7 @@ class IlluminanceLevelSensing(AttributeListeningChannel):
@registries.ZIGBEE_CHANNEL_REGISTRY.register( @registries.ZIGBEE_CHANNEL_REGISTRY.register(
measurement.IlluminanceMeasurement.cluster_id measurement.IlluminanceMeasurement.cluster_id
) )
class IlluminanceMeasurement(AttributeListeningChannel): class IlluminanceMeasurement(ZigbeeChannel):
"""Illuminance Measurement channel.""" """Illuminance Measurement channel."""
REPORT_CONFIG = [{"attr": "measured_value", "config": REPORT_CONFIG_DEFAULT}] REPORT_CONFIG = [{"attr": "measured_value", "config": REPORT_CONFIG_DEFAULT}]
@ -42,21 +42,21 @@ class IlluminanceMeasurement(AttributeListeningChannel):
@registries.BINARY_SENSOR_CLUSTERS.register(measurement.OccupancySensing.cluster_id) @registries.BINARY_SENSOR_CLUSTERS.register(measurement.OccupancySensing.cluster_id)
@registries.ZIGBEE_CHANNEL_REGISTRY.register(measurement.OccupancySensing.cluster_id) @registries.ZIGBEE_CHANNEL_REGISTRY.register(measurement.OccupancySensing.cluster_id)
class OccupancySensing(AttributeListeningChannel): class OccupancySensing(ZigbeeChannel):
"""Occupancy Sensing channel.""" """Occupancy Sensing channel."""
REPORT_CONFIG = [{"attr": "occupancy", "config": REPORT_CONFIG_IMMEDIATE}] REPORT_CONFIG = [{"attr": "occupancy", "config": REPORT_CONFIG_IMMEDIATE}]
@registries.ZIGBEE_CHANNEL_REGISTRY.register(measurement.PressureMeasurement.cluster_id) @registries.ZIGBEE_CHANNEL_REGISTRY.register(measurement.PressureMeasurement.cluster_id)
class PressureMeasurement(AttributeListeningChannel): class PressureMeasurement(ZigbeeChannel):
"""Pressure measurement channel.""" """Pressure measurement channel."""
REPORT_CONFIG = [{"attr": "measured_value", "config": REPORT_CONFIG_DEFAULT}] REPORT_CONFIG = [{"attr": "measured_value", "config": REPORT_CONFIG_DEFAULT}]
@registries.ZIGBEE_CHANNEL_REGISTRY.register(measurement.RelativeHumidity.cluster_id) @registries.ZIGBEE_CHANNEL_REGISTRY.register(measurement.RelativeHumidity.cluster_id)
class RelativeHumidity(AttributeListeningChannel): class RelativeHumidity(ZigbeeChannel):
"""Relative Humidity measurement channel.""" """Relative Humidity measurement channel."""
REPORT_CONFIG = [ REPORT_CONFIG = [
@ -70,7 +70,7 @@ class RelativeHumidity(AttributeListeningChannel):
@registries.ZIGBEE_CHANNEL_REGISTRY.register( @registries.ZIGBEE_CHANNEL_REGISTRY.register(
measurement.TemperatureMeasurement.cluster_id measurement.TemperatureMeasurement.cluster_id
) )
class TemperatureMeasurement(AttributeListeningChannel): class TemperatureMeasurement(ZigbeeChannel):
"""Temperature measurement channel.""" """Temperature measurement channel."""
REPORT_CONFIG = [ REPORT_CONFIG = [

View file

@ -124,7 +124,9 @@ class IASZoneChannel(ZigbeeChannel):
"""Handle commands received to this cluster.""" """Handle commands received to this cluster."""
if command_id == 0: if command_id == 0:
state = args[0] & 3 state = args[0] & 3
self.async_send_signal(f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", state) self.async_send_signal(
f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", 2, "zone_status", state
)
self.debug("Updated alarm state: %s", state) self.debug("Updated alarm state: %s", state)
elif command_id == 1: elif command_id == 1:
self.debug("Enroll requested") self.debug("Enroll requested")
@ -165,7 +167,12 @@ class IASZoneChannel(ZigbeeChannel):
"""Handle attribute updates on this cluster.""" """Handle attribute updates on this cluster."""
if attrid == 2: if attrid == 2:
value = value & 3 value = value & 3
self.async_send_signal(f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}", value) self.async_send_signal(
f"{self.unique_id}_{SIGNAL_ATTR_UPDATED}",
attrid,
self.cluster.attributes.get(attrid, [attrid])[0],
value,
)
async def async_initialize(self, from_cache): async def async_initialize(self, from_cache):
"""Initialize channel.""" """Initialize channel."""

View file

@ -8,7 +8,7 @@ from homeassistant.core import callback
from .. import registries, typing as zha_typing from .. import registries, typing as zha_typing
from ..const import REPORT_CONFIG_DEFAULT from ..const import REPORT_CONFIG_DEFAULT
from .base import AttributeListeningChannel, ZigbeeChannel from .base import ZigbeeChannel
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -70,7 +70,7 @@ class Messaging(ZigbeeChannel):
@registries.ZIGBEE_CHANNEL_REGISTRY.register(smartenergy.Metering.cluster_id) @registries.ZIGBEE_CHANNEL_REGISTRY.register(smartenergy.Metering.cluster_id)
class Metering(AttributeListeningChannel): class Metering(ZigbeeChannel):
"""Metering channel.""" """Metering channel."""
REPORT_CONFIG = [{"attr": "instantaneous_demand", "config": REPORT_CONFIG_DEFAULT}] REPORT_CONFIG = [{"attr": "instantaneous_demand", "config": REPORT_CONFIG_DEFAULT}]
@ -92,7 +92,7 @@ class Metering(AttributeListeningChannel):
} }
def __init__( def __init__(
self, cluster: zha_typing.ZigpyClusterType, ch_pool: zha_typing.ChannelPoolType, self, cluster: zha_typing.ZigpyClusterType, ch_pool: zha_typing.ChannelPoolType
) -> None: ) -> None:
"""Initialize Metering.""" """Initialize Metering."""
super().__init__(cluster, ch_pool) super().__init__(cluster, ch_pool)

View file

@ -134,7 +134,7 @@ class ProbeEndpoint:
continue continue
channel_class = zha_regs.ZIGBEE_CHANNEL_REGISTRY.get( channel_class = zha_regs.ZIGBEE_CHANNEL_REGISTRY.get(
cluster_id, base.AttributeListeningChannel cluster_id, base.ZigbeeChannel
) )
channel = channel_class(cluster, ep_channels) channel = channel_class(cluster, ep_channels)
self.probe_single_cluster(component, channel, ep_channels) self.probe_single_cluster(component, channel, ep_channels)

View file

@ -91,10 +91,10 @@ class ZhaCover(ZhaEntity, CoverDevice):
return self._current_position return self._current_position
@callback @callback
def async_set_position(self, pos): def async_set_position(self, attr_id, attr_name, value):
"""Handle position update from channel.""" """Handle position update from channel."""
_LOGGER.debug("setting position: %s", pos) _LOGGER.debug("setting position: %s", value)
self._current_position = 100 - pos self._current_position = 100 - value
if self._current_position == 0: if self._current_position == 0:
self._state = STATE_CLOSED self._state = STATE_CLOSED
elif self._current_position == 100: elif self._current_position == 100:
@ -102,7 +102,7 @@ class ZhaCover(ZhaEntity, CoverDevice):
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()
@callback @callback
def async_set_state(self, state): def async_update_state(self, state):
"""Handle state update from channel.""" """Handle state update from channel."""
_LOGGER.debug("state=%s", state) _LOGGER.debug("state=%s", state)
self._state = state self._state = state
@ -112,20 +112,20 @@ class ZhaCover(ZhaEntity, CoverDevice):
"""Open the window cover.""" """Open the window cover."""
res = await self._cover_channel.up_open() res = await self._cover_channel.up_open()
if isinstance(res, list) and res[1] is Status.SUCCESS: if isinstance(res, list) and res[1] is Status.SUCCESS:
self.async_set_state(STATE_OPENING) self.async_update_state(STATE_OPENING)
async def async_close_cover(self, **kwargs): async def async_close_cover(self, **kwargs):
"""Close the window cover.""" """Close the window cover."""
res = await self._cover_channel.down_close() res = await self._cover_channel.down_close()
if isinstance(res, list) and res[1] is Status.SUCCESS: if isinstance(res, list) and res[1] is Status.SUCCESS:
self.async_set_state(STATE_CLOSING) self.async_update_state(STATE_CLOSING)
async def async_set_cover_position(self, **kwargs): async def async_set_cover_position(self, **kwargs):
"""Move the roller shutter to a specific position.""" """Move the roller shutter to a specific position."""
new_pos = kwargs[ATTR_POSITION] new_pos = kwargs[ATTR_POSITION]
res = await self._cover_channel.go_to_lift_percentage(100 - new_pos) res = await self._cover_channel.go_to_lift_percentage(100 - new_pos)
if isinstance(res, list) and res[1] is Status.SUCCESS: if isinstance(res, list) and res[1] is Status.SUCCESS:
self.async_set_state( self.async_update_state(
STATE_CLOSING if new_pos < self._current_position else STATE_OPENING STATE_CLOSING if new_pos < self._current_position else STATE_OPENING
) )

View file

@ -83,8 +83,10 @@ class ZHADeviceScannerEntity(ScannerEntity, ZhaEntity):
return SOURCE_TYPE_ROUTER return SOURCE_TYPE_ROUTER
@callback @callback
def async_battery_percentage_remaining_updated(self, value): def async_battery_percentage_remaining_updated(self, attr_id, attr_name, value):
"""Handle tracking.""" """Handle tracking."""
if not attr_name == "battery_percentage_remaining":
return
self.debug("battery_percentage_remaining updated: %s", value) self.debug("battery_percentage_remaining updated: %s", value)
self._connected = True self._connected = True
self._battery_level = Battery.formatter(value) self._battery_level = Battery.formatter(value)

View file

@ -111,7 +111,7 @@ class ZhaEntity(RestoreEntity, LogMixin, entity.Entity):
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()
@callback @callback
def async_set_state(self, state): def async_set_state(self, attr_id, attr_name, value):
"""Set the entity state.""" """Set the entity state."""
pass pass

View file

@ -114,9 +114,9 @@ class ZhaFan(ZhaEntity, FanEntity):
return self.state_attributes return self.state_attributes
@callback @callback
def async_set_state(self, state): def async_set_state(self, attr_id, attr_name, value):
"""Handle state update from channel.""" """Handle state update from channel."""
self._state = VALUE_TO_SPEED.get(state, self._state) self._state = VALUE_TO_SPEED.get(value, self._state)
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()
async def async_turn_on(self, speed: str = None, **kwargs) -> None: async def async_turn_on(self, speed: str = None, **kwargs) -> None:
@ -133,7 +133,7 @@ class ZhaFan(ZhaEntity, FanEntity):
async def async_set_speed(self, speed: str) -> None: async def async_set_speed(self, speed: str) -> None:
"""Set the speed of the fan.""" """Set the speed of the fan."""
await self._fan_channel.async_set_speed(SPEED_TO_VALUE[speed]) await self._fan_channel.async_set_speed(SPEED_TO_VALUE[speed])
self.async_set_state(speed) self.async_set_state(0, "fan_mode", speed)
async def async_update(self): async def async_update(self):
"""Attempt to retrieve on off state from the fan.""" """Attempt to retrieve on off state from the fan."""

View file

@ -155,10 +155,10 @@ class Light(ZhaEntity, light.Light):
return self._supported_features return self._supported_features
@callback @callback
def async_set_state(self, state): def async_set_state(self, attr_id, attr_name, value):
"""Set the state.""" """Set the state."""
self._state = bool(state) self._state = bool(value)
if state: if value:
self._off_brightness = None self._off_brightness = None
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()

View file

@ -103,9 +103,9 @@ class ZhaDoorLock(ZhaEntity, LockDevice):
await self.async_get_state() await self.async_get_state()
@callback @callback
def async_set_state(self, state): def async_set_state(self, attr_id, attr_name, value):
"""Handle state update from channel.""" """Handle state update from channel."""
self._state = VALUE_TO_STATE.get(state, self._state) self._state = VALUE_TO_STATE.get(value, self._state)
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()
async def async_get_state(self, from_cache=True): async def async_get_state(self, from_cache=True):

View file

@ -124,11 +124,11 @@ class Sensor(ZhaEntity):
return self._state return self._state
@callback @callback
def async_set_state(self, state): def async_set_state(self, attr_id, attr_name, value):
"""Handle state update from channel.""" """Handle state update from channel."""
if state is not None: if value is not None:
state = self.formatter(state) value = self.formatter(value)
self._state = state self._state = value
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()
@callback @callback

View file

@ -71,9 +71,9 @@ class Switch(ZhaEntity, SwitchDevice):
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()
@callback @callback
def async_set_state(self, state): def async_set_state(self, attr_id, attr_name, value):
"""Handle state update from channel.""" """Handle state update from channel."""
self._state = bool(state) self._state = bool(value)
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()
@property @property

View file

@ -98,7 +98,7 @@ async def test_in_channel_config(
cluster = zigpy_dev.endpoints[1].in_clusters[cluster_id] cluster = zigpy_dev.endpoints[1].in_clusters[cluster_id]
channel_class = registries.ZIGBEE_CHANNEL_REGISTRY.get( channel_class = registries.ZIGBEE_CHANNEL_REGISTRY.get(
cluster_id, base_channels.AttributeListeningChannel cluster_id, base_channels.ZigbeeChannel
) )
channel = channel_class(cluster, channel_pool) channel = channel_class(cluster, channel_pool)
@ -156,7 +156,7 @@ async def test_out_channel_config(
cluster = zigpy_dev.endpoints[1].out_clusters[cluster_id] cluster = zigpy_dev.endpoints[1].out_clusters[cluster_id]
cluster.bind_only = True cluster.bind_only = True
channel_class = registries.ZIGBEE_CHANNEL_REGISTRY.get( channel_class = registries.ZIGBEE_CHANNEL_REGISTRY.get(
cluster_id, base_channels.AttributeListeningChannel cluster_id, base_channels.ZigbeeChannel
) )
channel = channel_class(cluster, channel_pool) channel = channel_class(cluster, channel_pool)