diff --git a/custom_components/adaptive_lighting/__init__.py b/custom_components/adaptive_lighting/__init__.py index 6b5f6c7d..88f81dc8 100755 --- a/custom_components/adaptive_lighting/__init__.py +++ b/custom_components/adaptive_lighting/__init__.py @@ -32,7 +32,13 @@ from homeassistant.components.switch import DOMAIN as SWITCH_DOMAIN from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry import homeassistant.helpers.config_validation as cv -from .const import _DOMAIN_SCHEMA, CONF_NAME, DOMAIN, UNDO_UPDATE_LISTENER +from .const import ( + _DOMAIN_SCHEMA, + ATTR_TURN_ON_OFF_LISTENER, + CONF_NAME, + DOMAIN, + UNDO_UPDATE_LISTENER, +) _LOGGER = logging.getLogger(__name__) @@ -93,7 +99,9 @@ async def async_unload_entry(hass, config_entry: ConfigEntry) -> bool: data = hass.data[DOMAIN] data[config_entry.entry_id][UNDO_UPDATE_LISTENER]() switch = data[config_entry.entry_id][SWITCH_DOMAIN] - switch._unsub_trackers() # pylint: disable=protected-access + switch._remove_listeners() # pylint: disable=protected-access + if len(data) == 1: # no more config_entries + data.pop(ATTR_TURN_ON_OFF_LISTENER).remove_listener() if unload_ok: data.pop(config_entry.entry_id) diff --git a/custom_components/adaptive_lighting/config_flow.py b/custom_components/adaptive_lighting/config_flow.py index a0c746a0..8b4e8936 100644 --- a/custom_components/adaptive_lighting/config_flow.py +++ b/custom_components/adaptive_lighting/config_flow.py @@ -92,6 +92,7 @@ class OptionsFlowHandler(config_entries.OptionsFlow): return self.async_create_entry(title="", data=user_input) all_lights = sorted(self.hass.states.async_entity_ids("light")) + # TODO: only use statefull entities all_entities = sorted(self.hass.states.async_entity_ids()) to_replace = { CONF_LIGHTS: cv.multi_select(all_lights), diff --git a/custom_components/adaptive_lighting/switch.py b/custom_components/adaptive_lighting/switch.py index 9c81c786..1cc5da93 100755 --- a/custom_components/adaptive_lighting/switch.py +++ b/custom_components/adaptive_lighting/switch.py @@ -246,7 +246,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity): self._hs_color = None # Set and unset tracker in async_turn_on and async_turn_off - self.unsub_trackers = [] + self.remove_listeners = [] _LOGGER.debug( "%s: Setting up with '%s'," " config_entry.data: '%s'," @@ -284,18 +284,15 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity): """Call when entity about to be added to hass.""" if self._lights: if self.hass.is_running: - await self._setup_trackers() + await self._setup_listeners() else: self.hass.bus.async_listen_once( - EVENT_HOMEASSISTANT_START, self._setup_trackers + EVENT_HOMEASSISTANT_START, self._setup_listeners ) last_state = await self.async_get_last_state() if last_state and last_state.state == STATE_ON: self._state = True - await self.async_turn_on( - adapt_lights=not self._only_once, - setup_listeners=False, - ) + await self.async_turn_on(adapt_lights=not self._only_once) else: self._state = False @@ -304,8 +301,10 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity): self.turn_on_off_listener.lights.update(all_lights) self._lights = list(all_lights) - async def _setup_trackers(self, _=None): - assert not self.unsub_trackers + async def _setup_listeners(self, _=None): + if not self.is_on: + return + assert not self.remove_listeners self._expand_light_groups() rm_interval = async_track_time_interval( self.hass, self._async_update_at_interval, self._interval @@ -313,23 +312,23 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity): rm_state = async_track_state_change_event( self.hass, self._lights, self._light_event ) - self.unsub_trackers.extend([rm_interval, rm_state]) + self.remove_listeners.extend([rm_interval, rm_state]) track_kwargs = dict(hass=self.hass, action=self._state_changed) if self._sleep_entity is not None: kwgs = dict(track_kwargs, entity_ids=self._sleep_entity) rm_from = async_track_state_change(**kwgs, from_state=self._sleep_state) rm_to = async_track_state_change(**kwgs, to_state=self._sleep_state) - self.unsub_trackers.extend([rm_from, rm_to]) + self.remove_listeners.extend([rm_from, rm_to]) if self._disable_entity is not None: kwgs = dict(track_kwargs, entity_ids=self._disable_entity) rm_from = async_track_state_change(**kwgs, from_state=self._disable_state) rm_to = async_track_state_change(**kwgs, to_state=self._disable_state) - self.unsub_trackers.extend([rm_from, rm_to]) + self.remove_listeners.extend([rm_from, rm_to]) - def _unsub_trackers(self): - while self.unsub_trackers: - unsub = self.unsub_trackers.pop() - unsub() + def _remove_listeners(self): + while self.remove_listeners: + remove_listener = self.remove_listeners.pop() + remove_listener() @property def icon(self): @@ -353,14 +352,13 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity): return attrs async def async_turn_on( - self, adapt_lights=True, setup_listeners=True + self, adapt_lights=True ): # pylint: disable=arguments-differ """Turn on adaptive lighting.""" if self.is_on: return self._state = True - if setup_listeners: - await self._setup_trackers() + await self._setup_listeners() if adapt_lights: await self._update_lights(transition=self._initial_transition, force=True) @@ -369,13 +367,13 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity): if not self.is_on: return self._state = False - self._unsub_trackers() + self._remove_listeners() async def _update_attrs(self): """Update Adaptive Values.""" # Setting all values because this method takes <0.5ms to execute. self._percent = self._calc_percent() - self._brightness = self._calc_brightness() # TODO: rename to brightness_pct + self._brightness = self._calc_brightness() self._color_temp_kelvin = self._calc_color_temp_kelvin() self._color_temp_mired = color_temperature_kelvin_to_mired( self._color_temp_kelvin @@ -543,13 +541,13 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity): context=Context(), ) - def _should_adjust(self): + def _should_adapt(self): if not self._lights or not self.is_on or self._is_disabled(): return False return True async def _adapt_lights(self, lights, transition): - if not self._should_adjust(): + if not self._should_adapt(): return _LOGGER.debug( "%s: '_adapt_lights(%s, %s)' called", self.name, lights, transition @@ -631,7 +629,9 @@ class TurnOnOffListener: self.sleep_tasks: Dict[str, asyncio.Task] = {} - self.hass.bus.async_listen(EVENT_CALL_SERVICE, self.turn_on_off_event_listener) + self.remove_listener = self.hass.bus.async_listen( + EVENT_CALL_SERVICE, self.turn_on_off_event_listener + ) async def maybe_cancel_adjusting( self, entity_id, off_to_on_event, on_to_off_event