diff --git a/apps/controller.py b/apps/controller.py index ad5cdea..efaae01 100644 --- a/apps/controller.py +++ b/apps/controller.py @@ -64,6 +64,7 @@ class ControllerRoomLights(ControllerEntities): if 'sleep' in self.args: self.get_entity(self.args['sleep']).set_state(state='on' if val else 'off') + @dataclass(init=False) class ControllerMotion(ControllerEntities): room: ControllerRoomLights @@ -154,7 +155,7 @@ class ControllerButton(Hass): self.room.is_sleeping = not self.room.is_sleeping if not self.room.is_sleeping: self.room.activate() - + @dataclass(init=False) class ControllerDaylight(Hass): @@ -162,7 +163,6 @@ class ControllerDaylight(Hass): entities: List[str] latitude: float longitude: float - enable: bool = field(init=False, default=True) def initialize(self): # convert room to App @@ -183,7 +183,14 @@ class ControllerDaylight(Hass): ) # self.log(self.adjuster) - self.listen_state(callback=self.handle_state_change, entity_id=[e.entity_id for e in self.entities]) + self.listen_state(callback=self.handle_state_change, + entity_id=[e.entity_id for e in self.entities]) + # self.listen_state(callback=self.handle_brightness_change, + # entity_id=[e.entity_id for e in self.entities], + # attribute='brightness') + # self.listen_state(callback=self.handle_brightness_change, + # entity_id=[e.entity_id for e in self.entities], + # attribute='color_temp') ents = [e.friendly_name for e in self.entities] if len(ents) > 1: ents[-1] = f'and {ents[-1]}' @@ -192,20 +199,23 @@ class ControllerDaylight(Hass): self.run_every(callback=self.update_sensors, start='now', interval=5.0) + for entity in self.entities: + if entity.get_state() == 'on': + self.start_adjustments(entity.entity_id) + def handle_state_change(self, entity=None, attribute=None, old=None, new=None, kwargs=None): + self.log(f'{entity}: {old} -> {new}') if new == 'on': - self.adjustment_handle = self.run_every( - callback=self.ongoing_adjustment, - start='now', - interval=10, - entity=entity - ) - self.log(f'Started adjustments') + if old == 'off': + self.start_adjustments(entity) else: - if hasattr(self, 'adjustment_handle'): - self.cancel_timer(self.adjustment_handle) - del self.adjustment_handle - self.log(f'Cancelled adjustments') + self.stop_adjustments() + + def handle_brightness_change(self, entity=None, attribute=None, old=None, new=None, kwargs=None): + if not self.matching_state(entity): + self.log(f'{entity}.{attribute}: {old} -> {new}') + self.log(f'State does not match adjuster settings, disabling adjustments') + self.stop_adjustments() def matching_state(self, entity_id: str) -> bool: """Checks whether the current state of the light matches the settings from the DaylightAdjuster @@ -215,17 +225,43 @@ class ControllerDaylight(Hass): Returns: bool - """ + """ state = self.get_state(entity_id=entity_id, attribute='all')['attributes'] settings = self.adjuster.current_settings try: state = {s: state[s] for s in settings.keys()} except KeyError: + for s in settings.keys(): + if s not in state: + self.log(f'{s} not in {state}') return False else: valid = all((state[s] == val) for s, val in settings.items()) + if not valid: + for s, val in settings.items(): + if state[s] != val: + self.log(f'{entity_id}.{s}: {state[s]} != {val}') return valid + @property + def enabled(self) -> bool: + return hasattr(self.adjustment_handle) + + def start_adjustments(self, entity: str): + self.adjustment_handle = self.run_every( + callback=self.ongoing_adjustment, + start='now', + interval=10, + entity=entity + ) + self.log(f'Started adjustments') + + def stop_adjustments(self): + if hasattr(self, 'adjustment_handle'): + self.cancel_timer(self.adjustment_handle) + del self.adjustment_handle + self.log(f'Cancelled adjustments') + def ongoing_adjustment(self, kwargs): self.log(f'Ongoing adjustment') settings = self.adjuster.current_settings @@ -233,12 +269,12 @@ class ControllerDaylight(Hass): if not matching and not self.room.is_sleeping: self.turn_on(entity_id=kwargs['entity'], **settings) self.log(f'Adjusted {self.friendly_name(kwargs["entity"])} with {settings}') - + def update_sensors(self, kwargs): for key, val in self.adjuster.current_settings.items(): id = f'sensor.{self.name}_{key}' self.set_state( entity_id=id, state=val, attributes={ - 'friendly_name': f'Daylight, {key}, {self.name}', - 'state_class': 'measurement'}) + 'friendly_name': f'Daylight, {key}, {self.name}', + 'state_class': 'measurement'})