diff --git a/homeassistant/components/zha/core/channels/general.py b/homeassistant/components/zha/core/channels/general.py index 621b0ccbee13eb..cd16fe5d22eda7 100644 --- a/homeassistant/components/zha/core/channels/general.py +++ b/homeassistant/components/zha/core/channels/general.py @@ -64,6 +64,13 @@ async def async_initialize(self, from_cache): await self.get_attribute_value(self.ON_OFF, from_cache=from_cache)) await super().async_initialize(from_cache) + async def async_update(self): + """Initialize channel.""" + _LOGGER.debug("Attempting to update onoff state") + self._state = bool( + await self.get_attribute_value(self.ON_OFF, from_cache=False)) + await super().async_update() + class LevelControlChannel(ZigbeeChannel): """Channel for the LevelControl Zigbee cluster.""" diff --git a/homeassistant/components/zha/core/channels/registry.py b/homeassistant/components/zha/core/channels/registry.py index f0363ac8330254..8f7335d82a9cd8 100644 --- a/homeassistant/components/zha/core/channels/registry.py +++ b/homeassistant/components/zha/core/channels/registry.py @@ -43,4 +43,5 @@ def populate_channel_registry(): zcl.clusters.general.Basic.cluster_id: BasicChannel, zcl.clusters.security.IasZone.cluster_id: IASZoneChannel, zcl.clusters.hvac.Fan.cluster_id: FanChannel, + zcl.clusters.lightlink.LightLink.cluster_id: ZigbeeChannel, }) diff --git a/homeassistant/components/zha/core/device.py b/homeassistant/components/zha/core/device.py index b0b41a87809671..06b33a418fbb7b 100644 --- a/homeassistant/components/zha/core/device.py +++ b/homeassistant/components/zha/core/device.py @@ -205,20 +205,22 @@ async def async_initialize(self, from_cache=False): async def _execute_channel_tasks(self, task_name, *args): """Gather and execute a set of CHANNEL tasks.""" channel_tasks = [] + semaphore = asyncio.Semaphore(3) for channel in self.all_channels: channel_tasks.append( - self._async_create_task(channel, task_name, *args)) + self._async_create_task(semaphore, channel, task_name, *args)) await asyncio.gather(*channel_tasks) - async def _async_create_task(self, channel, func_name, *args): + async def _async_create_task(self, semaphore, channel, func_name, *args): """Configure a single channel on this device.""" try: - await getattr(channel, func_name)(*args) - _LOGGER.debug('%s: channel: %s %s stage succeeded', - self.name, - "{}-{}".format( - channel.name, channel.unique_id), - func_name) + async with semaphore: + await getattr(channel, func_name)(*args) + _LOGGER.debug('%s: channel: %s %s stage succeeded', + self.name, + "{}-{}".format( + channel.name, channel.unique_id), + func_name) except Exception as ex: # pylint: disable=broad-except _LOGGER.warning( '%s channel: %s %s stage failed ex: %s', diff --git a/homeassistant/components/zha/core/gateway.py b/homeassistant/components/zha/core/gateway.py index a498e1e8ee17bd..595d32b1c2bb30 100644 --- a/homeassistant/components/zha/core/gateway.py +++ b/homeassistant/components/zha/core/gateway.py @@ -452,8 +452,11 @@ def establish_device_mappings(): NO_SENSOR_CLUSTERS.append(zcl.clusters.general.Basic.cluster_id) NO_SENSOR_CLUSTERS.append( zcl.clusters.general.PowerConfiguration.cluster_id) + NO_SENSOR_CLUSTERS.append(zcl.clusters.lightlink.LightLink.cluster_id) + BINDABLE_CLUSTERS.append(zcl.clusters.general.LevelControl.cluster_id) BINDABLE_CLUSTERS.append(zcl.clusters.general.OnOff.cluster_id) + BINDABLE_CLUSTERS.append(zcl.clusters.lighting.Color.cluster_id) DEVICE_CLASS[zha.PROFILE_ID].update({ zha.DeviceType.ON_OFF_SWITCH: 'binary_sensor', @@ -537,6 +540,7 @@ def establish_device_mappings(): zcl.clusters.general.PollControl.cluster_id: [], zcl.clusters.general.GreenPowerProxy.cluster_id: [], zcl.clusters.general.OnOffConfiguration.cluster_id: [], + zcl.clusters.lightlink.LightLink.cluster_id: [], zcl.clusters.general.OnOff.cluster_id: [{ 'attr': 'on_off', 'config': REPORT_CONFIG_IMMEDIATE diff --git a/homeassistant/components/zha/light.py b/homeassistant/components/zha/light.py index 740d67db1bd282..a87912eb213b85 100644 --- a/homeassistant/components/zha/light.py +++ b/homeassistant/components/zha/light.py @@ -4,6 +4,7 @@ For more details on this platform, please refer to the documentation at https://home-assistant.io/components/light.zha/ """ +from datetime import timedelta import logging from homeassistant.components import light @@ -26,6 +27,7 @@ CAPABILITIES_COLOR_TEMP = 0x10 UNSUPPORTED_ATTRIBUTE = 0x86 +SCAN_INTERVAL = timedelta(minutes=60) async def async_setup_platform(hass, config, async_add_entities, @@ -92,6 +94,11 @@ def __init__(self, unique_id, zha_device, channels, **kwargs): self._supported_features |= light.SUPPORT_COLOR self._hs_color = (0, 0) + @property + def should_poll(self) -> bool: + """Poll state from device.""" + return True + @property def is_on(self) -> bool: """Return true if entity is on.""" @@ -217,3 +224,8 @@ async def async_turn_off(self, **kwargs): return self._state = False self.async_schedule_update_ha_state() + + async def async_update(self): + """Attempt to retrieve on off state from the light.""" + if self._on_off_channel: + await self._on_off_channel.async_update() diff --git a/homeassistant/components/zha/switch.py b/homeassistant/components/zha/switch.py index bdbdd7a6a7680a..63a0cad93abc4a 100644 --- a/homeassistant/components/zha/switch.py +++ b/homeassistant/components/zha/switch.py @@ -71,11 +71,19 @@ def is_on(self) -> bool: async def async_turn_on(self, **kwargs): """Turn the entity on.""" - await self._on_off_channel.on() + success = await self._on_off_channel.on() + if not success: + return + self._state = True + self.async_schedule_update_ha_state() async def async_turn_off(self, **kwargs): """Turn the entity off.""" - await self._on_off_channel.off() + success = await self._on_off_channel.off() + if not success: + return + self._state = False + self.async_schedule_update_ha_state() def async_set_state(self, state): """Handle state update from channel."""