diff --git a/homeassistant/components/zha/light.py b/homeassistant/components/zha/light.py index efe95ae6604..f1bae3dd4c2 100644 --- a/homeassistant/components/zha/light.py +++ b/homeassistant/components/zha/light.py @@ -1,4 +1,5 @@ """Lights on Zigbee Home Automation networks.""" +import asyncio from collections import Counter from datetime import timedelta import functools @@ -31,6 +32,7 @@ from homeassistant.components.light import ( ) from homeassistant.const import ATTR_SUPPORTED_FEATURES, STATE_ON, STATE_UNAVAILABLE from homeassistant.core import State, callback +from homeassistant.helpers.debounce import Debouncer from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.event import async_track_time_interval import homeassistant.util.color as color_util @@ -406,7 +408,7 @@ class Light(BaseLight, ZhaEntity): async def async_get_state(self, from_cache=True): """Attempt to retrieve on off state from the light.""" - self.debug("polling current state") + self.debug("polling current state - from cache: %s", from_cache) if self._on_off_channel: state = await self._on_off_channel.get_attribute_value( "on_off", from_cache=from_cache @@ -494,6 +496,30 @@ class LightGroup(BaseLight, ZhaGroupEntity): self._level_channel = group.endpoint[LevelControl.cluster_id] self._color_channel = group.endpoint[Color.cluster_id] self._identify_channel = group.endpoint[Identify.cluster_id] + self._debounced_member_refresh = None + + async def async_added_to_hass(self): + """Run when about to be added to hass.""" + await super().async_added_to_hass() + if self._debounced_member_refresh is None: + force_refresh_debouncer = Debouncer( + self.hass, + _LOGGER, + cooldown=3, + immediate=True, + function=self._force_member_updates, + ) + self._debounced_member_refresh = force_refresh_debouncer + + async def async_turn_on(self, **kwargs): + """Turn the entity on.""" + await super().async_turn_on(**kwargs) + await self._debounced_member_refresh.async_call() + + async def async_turn_off(self, **kwargs): + """Turn the entity off.""" + await super().async_turn_off(**kwargs) + await self._debounced_member_refresh.async_call() async def async_update(self) -> None: """Query all members and determine the light group state.""" @@ -541,3 +567,11 @@ class LightGroup(BaseLight, ZhaGroupEntity): # Bitwise-and the supported features with the GroupedLight's features # so that we don't break in the future when a new feature is added. self._supported_features &= SUPPORT_GROUP_LIGHT + + async def _force_member_updates(self): + """Force the update of member entities to ensure the states are correct for bulbs that don't report their state.""" + component = self.hass.data[light.DOMAIN] + entities = [component.get_entity(entity_id) for entity_id in self._entity_ids] + tasks = [entity.async_get_state(from_cache=False) for entity in entities] + if tasks: + await asyncio.gather(*tasks)