From 143499cf51530790d5f0b9960da69f00448ceea6 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Fri, 7 Sep 2018 23:32:14 -0400 Subject: [PATCH 1/5] Add zha.configure_reporting() method. Binds a cluster and configures reporting for the specified attribute. --- homeassistant/components/zha/__init__.py | 39 ++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/homeassistant/components/zha/__init__.py b/homeassistant/components/zha/__init__.py index 7aec4333ea8c6d..c5974bda464af5 100644 --- a/homeassistant/components/zha/__init__.py +++ b/homeassistant/components/zha/__init__.py @@ -435,3 +435,42 @@ async def safe_read(cluster, attributes, allow_cache=True): return result except Exception: # pylint: disable=broad-except return {} + + +async def configure_reporting(entity_id, cluster, attr, skip_bind=False, + min_report=300, max_report=900, + reportable_change=1): + """Configure attribute reporting for a cluster. + + while swallowing the DeliverError exceptions in case of unreachable + devices. + """ + 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) + _LOGGER.debug( + "%s: reporting '%s' attr on '%s' cluster: %d/%d/%d: Status: %s", + entity_id, attr_name, cluster_name, min_report, max_report, + reportable_change, res[0][0].status + ) + except DeliveryError as ex: + _LOGGER.debug( + "%s: failed to set reporting for '%s' attr on '%s' cluster: %s", + entity_id, attr_name, cluster_name, str(ex) + ) From d4f854bb9346d2f7201f15a5f5bcad8ce457af32 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sat, 8 Sep 2018 17:05:43 -0400 Subject: [PATCH 2/5] git add homeassistant/components/binary_sensor/zha.py --- homeassistant/components/binary_sensor/zha.py | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/homeassistant/components/binary_sensor/zha.py b/homeassistant/components/binary_sensor/zha.py index cabbbd704a0014..1d026498f388e1 100644 --- a/homeassistant/components/binary_sensor/zha.py +++ b/homeassistant/components/binary_sensor/zha.py @@ -65,27 +65,24 @@ async def _async_setup_iaszone(hass, config, async_add_entities, async def _async_setup_remote(hass, config, async_add_entities, discovery_info): - async def safe(coro): - """Run coro, catching ZigBee delivery errors, and ignoring them.""" - import zigpy.exceptions - try: - await coro - except zigpy.exceptions.DeliveryError as exc: - _LOGGER.warning("Ignoring error during setup: %s", exc) + sensor = Switch(**discovery_info) if discovery_info['new_join']: from zigpy.zcl.clusters.general import OnOff, LevelControl out_clusters = discovery_info['out_clusters'] if OnOff.cluster_id in out_clusters: cluster = out_clusters[OnOff.cluster_id] - await safe(cluster.bind()) - await safe(cluster.configure_reporting(0, 0, 600, 1)) + await zha.configure_reporting( + sensor.entity_id, cluster, 0, min_report=0, max_report=600, + reportable_change=1 + ) if LevelControl.cluster_id in out_clusters: cluster = out_clusters[LevelControl.cluster_id] - await safe(cluster.bind()) - await safe(cluster.configure_reporting(0, 1, 600, 1)) + await zha.configure_reporting( + sensor.entity_id, cluster, 0, min_report=1, max_report=600, + reportable_change=1 + ) - sensor = Switch(**discovery_info) async_add_entities([sensor], update_before_add=True) From f00bbe212b33a5ea10ab5b5b7f0421bba5614e49 Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Sat, 8 Sep 2018 17:05:43 -0400 Subject: [PATCH 3/5] Refactor sensor.zha to use new 'configure_reporting() method. --- homeassistant/components/sensor/zha.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sensor/zha.py b/homeassistant/components/sensor/zha.py index 6202f8cb7efd29..0a6710f8f6cec9 100644 --- a/homeassistant/components/sensor/zha.py +++ b/homeassistant/components/sensor/zha.py @@ -57,9 +57,9 @@ def make_sensor(discovery_info): if discovery_info['new_join']: cluster = list(in_clusters.values())[0] - yield from cluster.bind() - yield from cluster.configure_reporting( - sensor.value_attribute, 300, 600, sensor.min_reportable_change, + yield from zha.configure_reporting( + sensor.entity_id, cluster, sensor.value_attribute, + reportable_change=sensor.min_reportable_change ) return sensor From 5fb206179618105bcc46b349d8367ba86edcf5e4 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sun, 9 Sep 2018 19:28:27 -0700 Subject: [PATCH 4/5] Zha configure reporting - switch (#1) * use configure_reporting for zha switch * lint fixes --- homeassistant/components/switch/zha.py | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/switch/zha.py b/homeassistant/components/switch/zha.py index 9f780b631b655f..9bf6fbbb82d6fb 100644 --- a/homeassistant/components/switch/zha.py +++ b/homeassistant/components/switch/zha.py @@ -21,13 +21,25 @@ async def async_setup_platform(hass, config, async_add_entities, if discovery_info is None: return + sensor = await make_sensor(discovery_info) + async_add_entities([sensor], update_before_add=True) + + +async def make_sensor(discovery_info): + """Create ZHA sensors factory.""" from zigpy.zcl.clusters.general import OnOff - in_clusters = discovery_info['in_clusters'] - cluster = in_clusters[OnOff.cluster_id] - await cluster.bind() - await cluster.configure_reporting(0, 0, 600, 1,) - async_add_entities([Switch(**discovery_info)], update_before_add=True) + sensor = Switch(**discovery_info) + + if discovery_info['new_join']: + in_clusters = discovery_info['in_clusters'] + cluster = in_clusters[OnOff.cluster_id] + await zha.configure_reporting( + sensor.entity_id, cluster, sensor.value_attribute, + min_report=0, max_report=600, reportable_change=1 + ) + + return sensor class Switch(zha.Entity, SwitchDevice): From 665e5b620a65f22b84aba324b20eeaa191fa6d6a Mon Sep 17 00:00:00 2001 From: Alexei Chetroi Date: Wed, 12 Sep 2018 13:41:34 -0400 Subject: [PATCH 5/5] Rename variables/classes to properly reflect the content --- homeassistant/components/binary_sensor/zha.py | 12 ++++++------ homeassistant/components/switch/zha.py | 16 +++++----------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/homeassistant/components/binary_sensor/zha.py b/homeassistant/components/binary_sensor/zha.py index 1d026498f388e1..0842ab7db6ea8f 100644 --- a/homeassistant/components/binary_sensor/zha.py +++ b/homeassistant/components/binary_sensor/zha.py @@ -65,7 +65,7 @@ async def _async_setup_iaszone(hass, config, async_add_entities, async def _async_setup_remote(hass, config, async_add_entities, discovery_info): - sensor = Switch(**discovery_info) + remote = Remote(**discovery_info) if discovery_info['new_join']: from zigpy.zcl.clusters.general import OnOff, LevelControl @@ -73,17 +73,17 @@ async def _async_setup_remote(hass, config, async_add_entities, if OnOff.cluster_id in out_clusters: cluster = out_clusters[OnOff.cluster_id] await zha.configure_reporting( - sensor.entity_id, cluster, 0, min_report=0, max_report=600, + remote.entity_id, cluster, 0, min_report=0, max_report=600, reportable_change=1 ) if LevelControl.cluster_id in out_clusters: cluster = out_clusters[LevelControl.cluster_id] await zha.configure_reporting( - sensor.entity_id, cluster, 0, min_report=1, max_report=600, + remote.entity_id, cluster, 0, min_report=1, max_report=600, reportable_change=1 ) - async_add_entities([sensor], update_before_add=True) + async_add_entities([remote], update_before_add=True) class BinarySensor(zha.Entity, BinarySensorDevice): @@ -128,7 +128,7 @@ def cluster_command(self, tsn, command_id, args): async def async_update(self): """Retrieve latest state.""" - from bellows.types.basic import uint16_t + from zigpy.types.basic import uint16_t result = await zha.safe_read(self._endpoint.ias_zone, ['zone_status'], @@ -138,7 +138,7 @@ async def async_update(self): self._state = result.get('zone_status', self._state) & 3 -class Switch(zha.Entity, BinarySensorDevice): +class Remote(zha.Entity, BinarySensorDevice): """ZHA switch/remote controller/button.""" _domain = DOMAIN diff --git a/homeassistant/components/switch/zha.py b/homeassistant/components/switch/zha.py index 9bf6fbbb82d6fb..7ac93180cd7703 100644 --- a/homeassistant/components/switch/zha.py +++ b/homeassistant/components/switch/zha.py @@ -17,29 +17,23 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Set up the Zigbee Home Automation switches.""" + from zigpy.zcl.clusters.general import OnOff + discovery_info = zha.get_discovery_info(hass, discovery_info) if discovery_info is None: return - sensor = await make_sensor(discovery_info) - async_add_entities([sensor], update_before_add=True) - - -async def make_sensor(discovery_info): - """Create ZHA sensors factory.""" - from zigpy.zcl.clusters.general import OnOff - - sensor = Switch(**discovery_info) + switch = Switch(**discovery_info) if discovery_info['new_join']: in_clusters = discovery_info['in_clusters'] cluster = in_clusters[OnOff.cluster_id] await zha.configure_reporting( - sensor.entity_id, cluster, sensor.value_attribute, + switch.entity_id, cluster, switch.value_attribute, min_report=0, max_report=600, reportable_change=1 ) - return sensor + async_add_entities([switch], update_before_add=True) class Switch(zha.Entity, SwitchDevice):