From 5e2296f2a45801bee07b5f64a641e700bc6c18e4 Mon Sep 17 00:00:00 2001 From: Steve Easley Date: Thu, 8 Mar 2018 22:31:52 -0500 Subject: [PATCH] Get zha switch and binary_sensor state on startup (#11672) * Get zha switch and binary_sensor state on startup * Removed unused var * Make zha switch report status * Use right method name * Formatting fix * Updates to match latest dev * PR feedback updates * Use async for cluster commands --- homeassistant/components/binary_sensor/zha.py | 33 ++++++++++---- homeassistant/components/switch/zha.py | 43 ++++++++++++++----- 2 files changed, 57 insertions(+), 19 deletions(-) diff --git a/homeassistant/components/binary_sensor/zha.py b/homeassistant/components/binary_sensor/zha.py index de7896e595b..bf038a62465 100644 --- a/homeassistant/components/binary_sensor/zha.py +++ b/homeassistant/components/binary_sensor/zha.py @@ -4,7 +4,6 @@ Binary sensors on Zigbee Home Automation networks. For more details on this platform, please refer to the documentation at https://home-assistant.io/components/binary_sensor.zha/ """ -import asyncio import logging from homeassistant.components.binary_sensor import DOMAIN, BinarySensorDevice @@ -25,8 +24,8 @@ CLASS_MAPPING = { } -@asyncio.coroutine -def async_setup_platform(hass, config, async_add_devices, discovery_info=None): +async def async_setup_platform(hass, config, async_add_devices, + discovery_info=None): """Set up the Zigbee Home Automation binary sensors.""" discovery_info = zha.get_discovery_info(hass, discovery_info) if discovery_info is None: @@ -39,19 +38,19 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None): device_class = None cluster = in_clusters[IasZone.cluster_id] if discovery_info['new_join']: - yield from cluster.bind() + await cluster.bind() ieee = cluster.endpoint.device.application.ieee - yield from cluster.write_attributes({'cie_addr': ieee}) + await cluster.write_attributes({'cie_addr': ieee}) try: - zone_type = yield from cluster['zone_type'] + zone_type = await cluster['zone_type'] device_class = CLASS_MAPPING.get(zone_type, None) except Exception: # pylint: disable=broad-except # If we fail to read from the device, use a non-specific class pass sensor = BinarySensor(device_class, **discovery_info) - async_add_devices([sensor]) + async_add_devices([sensor], update_before_add=True) class BinarySensor(zha.Entity, BinarySensorDevice): @@ -66,6 +65,11 @@ class BinarySensor(zha.Entity, BinarySensorDevice): from zigpy.zcl.clusters.security import IasZone self._ias_zone_cluster = self._in_clusters[IasZone.cluster_id] + @property + def should_poll(self) -> bool: + """Let zha handle polling.""" + return False + @property def is_on(self) -> bool: """Return True if entity is on.""" @@ -83,7 +87,18 @@ class BinarySensor(zha.Entity, BinarySensorDevice): if command_id == 0: self._state = args[0] & 3 _LOGGER.debug("Updated alarm state: %s", self._state) - self.schedule_update_ha_state() + self.async_schedule_update_ha_state() elif command_id == 1: _LOGGER.debug("Enroll requested") - self.hass.add_job(self._ias_zone_cluster.enroll_response(0, 0)) + res = self._ias_zone_cluster.enroll_response(0, 0) + self.hass.async_add_job(res) + + async def async_update(self): + """Retrieve latest state.""" + from bellows.types.basic import uint16_t + + result = await zha.safe_read(self._endpoint.ias_zone, + ['zone_status']) + state = result.get('zone_status', self._state) + if isinstance(state, (int, uint16_t)): + self._state = result.get('zone_status', self._state) & 3 diff --git a/homeassistant/components/switch/zha.py b/homeassistant/components/switch/zha.py index c98db2e894e..7de9f1459b1 100644 --- a/homeassistant/components/switch/zha.py +++ b/homeassistant/components/switch/zha.py @@ -4,7 +4,6 @@ Switches on Zigbee Home Automation networks. For more details on this platform, please refer to the documentation at https://home-assistant.io/components/switch.zha/ """ -import asyncio import logging from homeassistant.components.switch import DOMAIN, SwitchDevice @@ -15,19 +14,39 @@ _LOGGER = logging.getLogger(__name__) DEPENDENCIES = ['zha'] -def setup_platform(hass, config, add_devices, discovery_info=None): - """Set up Zigbee Home Automation switches.""" +async def async_setup_platform(hass, config, async_add_devices, + discovery_info=None): + """Set up the Zigbee Home Automation switches.""" discovery_info = zha.get_discovery_info(hass, discovery_info) if discovery_info is None: return - add_devices([Switch(**discovery_info)]) + 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_devices([Switch(**discovery_info)], update_before_add=True) class Switch(zha.Entity, SwitchDevice): """ZHA switch.""" _domain = DOMAIN + value_attribute = 0 + + def attribute_updated(self, attribute, value): + """Handle attribute update from device.""" + _LOGGER.debug("Attribute updated: %s %s %s", self, attribute, value) + if attribute == self.value_attribute: + self._state = value + self.async_schedule_update_ha_state() + + @property + def should_poll(self) -> bool: + """Let zha handle polling.""" + return False @property def is_on(self) -> bool: @@ -36,14 +55,18 @@ class Switch(zha.Entity, SwitchDevice): return False return bool(self._state) - @asyncio.coroutine - def async_turn_on(self, **kwargs): + async def async_turn_on(self, **kwargs): """Turn the entity on.""" - yield from self._endpoint.on_off.on() + await self._endpoint.on_off.on() self._state = 1 - @asyncio.coroutine - def async_turn_off(self, **kwargs): + async def async_turn_off(self, **kwargs): """Turn the entity off.""" - yield from self._endpoint.on_off.off() + await self._endpoint.on_off.off() self._state = 0 + + async def async_update(self): + """Retrieve latest state.""" + result = await zha.safe_read(self._endpoint.on_off, + ['on_off']) + self._state = result.get('on_off', self._state)