import appdaemon.plugins.hass.hassapi as hass class EveningModeLighting(hass.Hass): def initialize(self): self.set_log_level("DEBUG") # Read configuration self.target_brightness = self.args["target_brightness"] self.target_color_temp = self.args["target_color_temp"] self.evening_mode_entity = self.args["evening_mode_entity"] self.exclude_entities = self.args.get("exclude_entities", []) self.light_listeners: list[str] = [] # Listen to changes in the evening mode toggle self.listen_state(self.evening_mode_change, self.evening_mode_entity) # Initialize based on current state of evening mode if self.get_state(self.evening_mode_entity) == "on": self.setup_listeners() def evening_mode_change(self, entity, attribute, old, new, kwargs): if new == "on": self.setup_listeners() else: self.teardown_listeners() def setup_listeners(self): # Get all light entities and filter out the excluded ones and those that don't support dimming all_light_entities = self.get_state("light") # Set up listeners for light state changes self.light_listeners = [] for light in all_light_entities: if ( light in self.exclude_entities or not self.supports_dimming(light) or self.is_group(light) ): continue listener = self.listen_state(self.light_state_change, light) self.log( "Listening to light events for %s: %s", light, listener, level="INFO" ) self.light_listeners.append(listener) self.log("Listening to %d lights", len(self.light_listeners)) def teardown_listeners(self): # Cancel all light state listeners for listener in self.light_listeners: self.cancel_listen_state(listener) self.log("Canceled light event listener: %s", listener, level="INFO") self.light_listeners = [] def light_state_change(self, entity, attribute, old, new, kwargs): # Check if the light is being turned on if old in ("off", "unavailable") and new == "on": # Get the brightness attribute of the light brightness = self.get_state(entity, attribute="brightness") brightness_pct = int(brightness / 255 * 100) # Check if the brightness exceeds the target value if brightness_pct and brightness_pct > self.target_brightness: self.log("Dimming light %s", entity, level="INFO") # Dim the light to the target brightness self.turn_on( entity, brightness_pct=self.target_brightness, color_temp=self.target_color_temp, ) else: self.log("Light state changed, but no action: entity=%s, old=%s, new=%s", entity, old, new) def is_group(self, entity) -> bool: # Check if the light entity is a group attributes = self.get_state(entity, attribute="attributes") if attributes.get("is_hue_group", False) or attributes.get("entity_id", []): self.log( "Skipping light entity %s because it's a group", entity, level="DEBUG" ) return True return False def supports_dimming(self, entity): # Check if the light entity supports dimming if self.get_state(entity, attribute="supported_features", default=0): return True self.log( "Skipping light entity %s because it doesn't support dimming", entity, level="DEBUG", ) return False