From 2b35ee1e5e8959a1315384536792f036b2ce6b2c Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Sun, 30 Jul 2023 11:49:40 -0700 Subject: [PATCH 1/5] Mark as manually controlled when using flash, effect, or RGBW(W) (#684) * Mark as manually controlled when using flash or effect * Add comment * Add RGBW and RGBWW --- .../adaptive_lighting/adaptation_utils.py | 5 +++++ custom_components/adaptive_lighting/switch.py | 10 ++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/custom_components/adaptive_lighting/adaptation_utils.py b/custom_components/adaptive_lighting/adaptation_utils.py index 99d1eea5..e0ab6c47 100644 --- a/custom_components/adaptive_lighting/adaptation_utils.py +++ b/custom_components/adaptive_lighting/adaptation_utils.py @@ -13,6 +13,8 @@ from homeassistant.components.light import ( ATTR_COLOR_TEMP_KELVIN, ATTR_HS_COLOR, ATTR_RGB_COLOR, + ATTR_RGBW_COLOR, + ATTR_RGBWW_COLOR, ATTR_TRANSITION, ATTR_XY_COLOR, ) @@ -27,8 +29,11 @@ COLOR_ATTRS = { # Should ATTR_PROFILE be in here? ATTR_HS_COLOR, ATTR_RGB_COLOR, ATTR_XY_COLOR, + ATTR_RGBW_COLOR, + ATTR_RGBWW_COLOR, } + BRIGHTNESS_ATTRS = { ATTR_BRIGHTNESS, ATTR_BRIGHTNESS_PCT, diff --git a/custom_components/adaptive_lighting/switch.py b/custom_components/adaptive_lighting/switch.py index 9f2c11e3..181bd20d 100644 --- a/custom_components/adaptive_lighting/switch.py +++ b/custom_components/adaptive_lighting/switch.py @@ -21,6 +21,8 @@ import voluptuous as vol from homeassistant.components.light import ( ATTR_BRIGHTNESS, ATTR_COLOR_TEMP_KELVIN, + ATTR_EFFECT, + ATTR_FLASH, ATTR_RGB_COLOR, ATTR_SUPPORTED_COLOR_MODES, ATTR_TRANSITION, @@ -1450,6 +1452,7 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity): context.id, ) else: + # Need to fire manual control event because of significant_change _fire_manual_control_event(self, light, context) else: _LOGGER.debug( @@ -2371,8 +2374,11 @@ class AdaptiveLightingManager: and not force ): keys = turn_on_event.data[ATTR_SERVICE_DATA].keys() - if (adapt_color and COLOR_ATTRS.intersection(keys)) or ( - adapt_brightness and BRIGHTNESS_ATTRS.intersection(keys) + if ( + (adapt_color and COLOR_ATTRS.intersection(keys)) + or (adapt_brightness and BRIGHTNESS_ATTRS.intersection(keys)) + or (ATTR_FLASH in keys) + or (ATTR_EFFECT in keys) ): # Light was already on and 'light.turn_on' was not called by # the adaptive_lighting integration. From 2e25af3125544bb77720fcca270f61f01b6d87f8 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Sun, 30 Jul 2023 12:32:59 -0700 Subject: [PATCH 2/5] Do not intercept effect and flash calls (#685) * Do not intercept effect and flash calls * log * Do not intercept flash --- custom_components/adaptive_lighting/switch.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/custom_components/adaptive_lighting/switch.py b/custom_components/adaptive_lighting/switch.py index 181bd20d..58638c3d 100644 --- a/custom_components/adaptive_lighting/switch.py +++ b/custom_components/adaptive_lighting/switch.py @@ -2003,6 +2003,9 @@ class AdaptiveLightingManager: if is_our_context(call.context): return + if ATTR_EFFECT in data[CONF_PARAMS] or ATTR_FLASH in data[CONF_PARAMS]: + return + entity_ids = self._get_entity_list(data) # For simplicity, only service calls affecting a single entity are currently handled. From f4d872a54089a05f84292e0f58cb8e9d95562181 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Sun, 30 Jul 2023 13:01:08 -0700 Subject: [PATCH 3/5] Make sure that SimpleSwitches are added before AdaptiveSwitch (#686) --- custom_components/adaptive_lighting/switch.py | 24 +++++++++++++++---- tests/test_switch.py | 3 +-- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/custom_components/adaptive_lighting/switch.py b/custom_components/adaptive_lighting/switch.py index 58638c3d..2cf2c5db 100644 --- a/custom_components/adaptive_lighting/switch.py +++ b/custom_components/adaptive_lighting/switch.py @@ -293,7 +293,7 @@ def _switches_with_lights( entry = data.get(config.entry_id) if entry is None: # entry might be disabled and therefore missing continue - switch = data[config.entry_id]["instance"] + switch = data[config.entry_id][SWITCH_DOMAIN] switch._expand_light_groups() # Check if any of the lights are in the switch's lights if set(switch.lights) & set(all_check_lights): @@ -367,7 +367,7 @@ def _switches_from_service_call( ent_entry = ent_reg.async_get(entity_id) assert ent_entry is not None config_id = ent_entry.config_entry_id - switches.append(hass.data[DOMAIN][config_id]["instance"]) + switches.append(hass.data[DOMAIN][config_id][SWITCH_DOMAIN]) return switches if lights: @@ -498,9 +498,6 @@ async def async_setup_entry( # noqa: PLR0915 adapt_brightness_switch, ) - # save our switch instance, allows us to make switch's entity_id optional in service calls. - hass.data[DOMAIN][config_entry.entry_id]["instance"] = switch - data[config_entry.entry_id][SLEEP_MODE_SWITCH] = sleep_mode_switch data[config_entry.entry_id][ADAPT_COLOR_SWITCH] = adapt_color_switch data[config_entry.entry_id][ADAPT_BRIGHTNESS_SWITCH] = adapt_brightness_switch @@ -1016,6 +1013,23 @@ class AdaptiveSwitch(SwitchEntity, RestoreEntity): _LOGGER.debug("%s: Cancelled '_setup_listeners'", self._name) return + while not all( + sw._state is not None + for sw in [ + self.sleep_mode_switch, + self.adapt_brightness_switch, + self.adapt_color_switch, + ] + ): + # Waits until `async_added_to_hass` is done, which in SimpleSwitch + # is when `_state` is set to `True` or `False`. + # Fixes first issue in https://github.com/basnijholt/adaptive-lighting/issues/682 + _LOGGER.debug( + "%s: Waiting for simple switches to be initialized", + self._name, + ) + await asyncio.sleep(0.1) + assert not self.remove_listeners self._update_time_interval_listener() diff --git a/tests/test_switch.py b/tests/test_switch.py index be0c7d37..2a49f41c 100644 --- a/tests/test_switch.py +++ b/tests/test_switch.py @@ -331,9 +331,8 @@ async def test_adaptive_lighting_switches(hass): assert ADAPT_COLOR_SWITCH in data assert ADAPT_BRIGHTNESS_SWITCH in data assert UNDO_UPDATE_LISTENER in data - assert "instance" in data - assert len(data.keys()) == 6 + assert len(data.keys()) == 5 @pytest.mark.parametrize("lat,long,timezone", LAT_LONG_TZS) From e98f0dfa550f6f2d7e4b00a61e8ec7767a860a53 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Sun, 30 Jul 2023 13:11:30 -0700 Subject: [PATCH 4/5] Bump to 1.18.1 --- custom_components/adaptive_lighting/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/custom_components/adaptive_lighting/manifest.json b/custom_components/adaptive_lighting/manifest.json index 34045b68..87996208 100644 --- a/custom_components/adaptive_lighting/manifest.json +++ b/custom_components/adaptive_lighting/manifest.json @@ -8,5 +8,5 @@ "iot_class": "calculated", "issue_tracker": "https://github.com/basnijholt/adaptive-lighting/issues", "requirements": ["ulid-transform"], - "version": "1.18.0" + "version": "1.18.1" } From 1842ac9bd5db62e7af8fd2ead12121abd870edb2 Mon Sep 17 00:00:00 2001 From: Bas Nijholt Date: Sun, 30 Jul 2023 13:28:58 -0700 Subject: [PATCH 5/5] Do not assert but issue a warning (#687) * Do not assert but issue a warning * bump to 1.18.2 --- custom_components/adaptive_lighting/manifest.json | 2 +- custom_components/adaptive_lighting/switch.py | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/custom_components/adaptive_lighting/manifest.json b/custom_components/adaptive_lighting/manifest.json index 87996208..8d6a80b9 100644 --- a/custom_components/adaptive_lighting/manifest.json +++ b/custom_components/adaptive_lighting/manifest.json @@ -8,5 +8,5 @@ "iot_class": "calculated", "issue_tracker": "https://github.com/basnijholt/adaptive-lighting/issues", "requirements": ["ulid-transform"], - "version": "1.18.1" + "version": "1.18.2" } diff --git a/custom_components/adaptive_lighting/switch.py b/custom_components/adaptive_lighting/switch.py index 2cf2c5db..a96351f2 100644 --- a/custom_components/adaptive_lighting/switch.py +++ b/custom_components/adaptive_lighting/switch.py @@ -2476,7 +2476,16 @@ class AdaptiveLightingManager: off_to_on_event: Event, ) -> bool: # Adaptive Lighting should never turn on lights itself - assert not is_our_context(off_to_on_event.context) + if is_our_context(off_to_on_event.context): + _LOGGER.warning( + "Detected an 'off' → 'on' event for '%s' with context.id='%s' and" + " event='%s', triggered by the adaptive_lighting integration itself," + " which *should* not happen. If you see this please submit an issue with" + " your full logs at https://github.com/basnijholt/adaptive-lighting", + entity_id, + off_to_on_event.context.id, + off_to_on_event, + ) turn_on_event: Event | None = self.turn_on_event.get(entity_id) id_off_to_on = off_to_on_event.context.id return (