diff --git a/homeassistant/components/binary_sensor/zha.py b/homeassistant/components/binary_sensor/zha.py index 9314c727bcb..0d426f0aa14 100644 --- a/homeassistant/components/binary_sensor/zha.py +++ b/homeassistant/components/binary_sensor/zha.py @@ -179,12 +179,6 @@ class Remote(RestoreEntity, ZhaEntity, BinarySensorDevice): out_clusters = kwargs.get('out_clusters') self._zcl_reporting = {} - for cluster_id in [general.OnOff.cluster_id, - general.LevelControl.cluster_id]: - if cluster_id not in out_clusters: - continue - cluster = out_clusters[cluster_id] - self._zcl_reporting[cluster] = {0: REPORT_CONFIG_IMMEDIATE} if general.LevelControl.cluster_id in out_clusters: self._out_listeners.update({ @@ -233,6 +227,19 @@ class Remote(RestoreEntity, ZhaEntity, BinarySensorDevice): self._level = 255 self.async_schedule_update_ha_state() + async def async_configure(self): + """Bind clusters.""" + from zigpy.zcl.clusters import general + await helpers.bind_cluster( + self.entity_id, + self._out_clusters[general.OnOff.cluster_id] + ) + if general.LevelControl.cluster_id in self._out_clusters: + await helpers.bind_cluster( + self.entity_id, + self._out_clusters[general.LevelControl.cluster_id] + ) + async def async_added_to_hass(self): """Run when about to be added to hass.""" await super().async_added_to_hass() diff --git a/homeassistant/components/zha/entities/entity.py b/homeassistant/components/zha/entities/entity.py index 41493b487a3..dadd79e82a5 100644 --- a/homeassistant/components/zha/entities/entity.py +++ b/homeassistant/components/zha/entities/entity.py @@ -10,7 +10,7 @@ from random import uniform from homeassistant.components.zha.const import ( DATA_ZHA, DATA_ZHA_BRIDGE_ID, DOMAIN) -from homeassistant.components.zha.helpers import configure_reporting +from homeassistant.components.zha.helpers import bind_configure_reporting from homeassistant.core import callback from homeassistant.helpers import entity from homeassistant.helpers.device_registry import CONNECTION_ZIGBEE @@ -100,7 +100,7 @@ class ZhaEntity(entity.Entity): skip_bind = False # bind cluster only for the 1st configured attr for attr, details in attrs.items(): min_report_interval, max_report_interval, change = details - await configure_reporting( + await bind_configure_reporting( self.entity_id, cluster, attr, min_report=min_report_interval, max_report=max_report_interval, diff --git a/homeassistant/components/zha/helpers.py b/homeassistant/components/zha/helpers.py index 7333cb92254..426bceeb634 100644 --- a/homeassistant/components/zha/helpers.py +++ b/homeassistant/components/zha/helpers.py @@ -32,6 +32,27 @@ async def safe_read(cluster, attributes, allow_cache=True, only_cache=False): return {} +async def bind_cluster(entity_id, cluster): + """Bind a zigbee cluster. + + This also swallows DeliveryError exceptions that are thrown when devices + are unreachable. + """ + from zigpy.exceptions import DeliveryError + + cluster_name = cluster.ep_attribute + try: + res = await cluster.bind() + _LOGGER.debug( + "%s: bound '%s' cluster: %s", entity_id, cluster_name, res[0] + ) + except DeliveryError as ex: + _LOGGER.debug( + "%s: Failed to bind '%s' cluster: %s", + entity_id, cluster_name, str(ex) + ) + + async def configure_reporting(entity_id, cluster, attr, skip_bind=False, min_report=REPORT_CONFIG_MIN_INT, max_report=REPORT_CONFIG_MAX_INT, @@ -39,25 +60,13 @@ async def configure_reporting(entity_id, cluster, attr, skip_bind=False, manufacturer=None): """Configure attribute reporting for a cluster. - while swallowing the DeliverError exceptions in case of unreachable - devices. + This also swallows DeliveryError exceptions that are thrown when devices + are unreachable. """ from zigpy.exceptions import DeliveryError attr_name = cluster.attributes.get(attr, [attr])[0] cluster_name = cluster.ep_attribute - if not skip_bind: - try: - res = await cluster.bind() - _LOGGER.debug( - "%s: bound '%s' cluster: %s", entity_id, cluster_name, res[0] - ) - except DeliveryError as ex: - _LOGGER.debug( - "%s: Failed to bind '%s' cluster: %s", - entity_id, cluster_name, str(ex) - ) - try: res = await cluster.configure_reporting(attr, min_report, max_report, reportable_change, @@ -74,6 +83,26 @@ async def configure_reporting(entity_id, cluster, attr, skip_bind=False, ) +async def bind_configure_reporting(entity_id, cluster, attr, skip_bind=False, + min_report=REPORT_CONFIG_MIN_INT, + max_report=REPORT_CONFIG_MAX_INT, + reportable_change=REPORT_CONFIG_RPT_CHANGE, + manufacturer=None): + """Bind and configure zigbee attribute reporting for a cluster. + + This also swallows DeliveryError exceptions that are thrown when devices + are unreachable. + """ + if not skip_bind: + await bind_cluster(entity_id, cluster) + + await configure_reporting(entity_id, cluster, attr, skip_bind=False, + min_report=REPORT_CONFIG_MIN_INT, + max_report=REPORT_CONFIG_MAX_INT, + reportable_change=REPORT_CONFIG_RPT_CHANGE, + manufacturer=None) + + async def check_zigpy_connection(usb_path, radio_type, database_path): """Test zigpy radio connection.""" if radio_type == RadioType.ezsp.name: